Написать реализацию метода в базовом классе, который требует переопределения в подклассах? - PullRequest
4 голосов
/ 14 ноября 2011

На Яве ...

Я создаю класс Foo, который содержит метод doAction (). Мои требования:

  1. doAction () должна иметь реализацию по умолчанию (т.е. тело функции) в Foo.
  2. Все подклассы Foo должны переопределять doAction (), что означает, что подклассы получат ошибку компилятора, если они не предоставляют новую реализацию.
  3. Мне нужно иметь возможность создавать Foo.

abstract будет работать, за исключением того, что он не позволяет мне указывать тело функции для doAction ().

Ответы [ 5 ]

5 голосов
/ 14 ноября 2011

Редактировать

Невозможно одновременно удовлетворить все требования, конец истории. Вы должны отказаться хотя бы от одного условия и, возможно, рассмотреть совершенно другой подход к проблеме, которую вы пытаетесь решить.


Используйте два отдельных метода. Или:

abstract class Foo {

    // Override this method
    abstract void doActionInSubclass();

    // You can't override a final method
    // And you don't want subclases to override this one
    final void doAction () {
        // do whatever default-y things you want here
        doActionInSubclass();
    }
}

Или просто выделите «требуемый» метод полностью отдельно от того, который вы хотите переопределить подклассами:

abstract class Foo {
    abstract void mustOverrideThisInConcreteSubclasses();

    final void doAction() {
        // default-y things here
    }
}
3 голосов
/ 14 ноября 2011

Если вы дадите реализацию по умолчанию для метода в Java, вы не сможете заставить подклассы переопределить его снова.Если вы можете, используйте шаблон шаблон шаблон с другим именем метода:

public class Foo{

    public abstract void templateMethod();
    public final void doAction(){

    //default implementation

     templateMethod(); // call template method
    }
}
0 голосов
/ 14 ноября 2011

В конструкторе (ах) класса Foo вы можете использовать отражение :

class Foo {
    public Foo() {
        Class c = getClass();
        if (!c.equals(Foo.class))
        {
            // try/catch omitted for brevity
            Method m = c.getMethod("methodName", new Class[0]);
            if (m.getDeclaringClass().equals(Foo.class))
            {
                throw new Exception("blah blah blah");
            }
        }
    }
}

Это не приведет к ошибке времени компиляции, но так как вызовsuper() в конструкторе не может быть заключен в try никто не может создать подкласс, чтобы обойти его.

0 голосов
/ 14 ноября 2011

Если все подклассы должны переопределять его, почему вы хотите предоставить реализацию по умолчанию ?!это было бы бессмысленно, поскольку никто не использовал бы его.Однако у вас, вероятно, есть некоторый код вашего doAction, который вы хотите выполнить любыми подклассами, и некоторый код, который вы хотите переопределить.В этом случае вы могли бы спроектировать так:

doAction(){
     //put your default code here...
     specificAction();
}

abstract specificAction();

Таким образом, doAction имеет свою собственную реализацию, которая заканчивается вызовом specificAction, который вместо этого должен быть реализован подклассами

0 голосов
/ 14 ноября 2011

Реализуйте свой метод в Foo и сделайте так, чтобы он всегда выдавал исключение, например UnsupportedOperationException.Это потребует от подклассов переопределить метод.

...