Java: сделать метод абстрактным для каждого расширяющего класса - PullRequest
2 голосов
/ 30 апреля 2010

Есть ли ключевое слово или шаблон дизайна для этого?

Пожалуйста, проверьте обновление

public abstract class Root
{
    public abstract void foo();
}

public abstract class SubClass extends Root
{
    public void foo()
    {
        // Do something
        //---------------- Update -------------------//
        // This method contains important code
        // that is needed when I'm using a instance
        // of SubClass and it is no instance of any
        // other class extending SubClass

    }
}

public class SubberClass extends SubClass
{
    // Here is it not necessary to override foo()
    // So is there a way to make this necessary? 
    // A way to obligate the developer make again the override 
}

Спасибо

Ответы [ 6 ]

9 голосов
/ 30 апреля 2010

Если вы делаете это, то вы, вероятно, злоупотребляете наследованием; Наследование, вопреки распространенному мифу, предназначено не для создания пользовательских хуков / обработчиков, а для включения альтернативных реализаций.

Если вы хотите, чтобы ваш пользователь предоставлял какую-то функцию / ловушку / обратный вызов, то вы должны определить интерфейс, который предоставляет только те методы, которые должен определить ваш пользователь. Затем вы должны потребовать от пользователя передать экземпляр этого интерфейса конструктору вашего объекта или передать функции, которая в этом нуждается.

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

3 голосов
/ 30 апреля 2010

Если каждый подкласс класса SubClass должен переопределять foo(), тогда зачем вообще предоставлять реализацию в SubClass? Вы можете просто удалить определение метода из SubClass, и тогда все подклассы будут вынуждены предоставить реализацию.

1 голос
/ 30 апреля 2010

Если вы действительно хотите, вы можете повторно объявить foo как абстрактный.

public abstract class SubberClass extends SubClass
{
    public abstract void foo();
}
0 голосов
/ 30 апреля 2010

Вы не можете иметь это в обоих направлениях. Вы не можете предоставить метод с реализацией по умолчанию И требовать, чтобы дочерние классы переопределяли его. Вместо того, чтобы объявлять метод как абстрактный в Root, вы можете определить интерфейс (IFoo) с объявленным методом, а затем предоставить абстрактный класс, который реализует интерфейс. Это по-прежнему требует конкретного дочернего класса, но не требует переопределения метода.

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

В любом случае вы не можете предоставить поведение по умолчанию для одного метода и требовать, чтобы дочерние классы переопределяли этот же метод.

0 голосов
/ 30 апреля 2010

Да, нет необходимости переопределять foo() в SubberClass.

0 голосов
/ 30 апреля 2010

Вместо переопределения foo() в SubClass создайте новый метод fooImpl() и оставьте foo() абстрактным. Таким образом, все классы должны реализовывать foo(), но вы можете просто реализовать его, вызвав fooImpl(), если этого уже достаточно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...