Есть ли способ сделать метод, который не был бы абстрактным, но его нужно было бы переопределить?

StackOverflow https://stackoverflow.com/questions/7832444

Вопрос

Есть ли способ заставить дочерние классы переопределять неабстрактный метод суперкласса?

Мне нужно иметь возможность создавать экземпляры родительского класса, но если класс расширяет этот класс, он должен давать собственное определение некоторых методов.

Это было полезно?

Решение

Насколько мне известно, прямого способа сделать это с помощью компилятора не существует.

Вы можете обойти это, не создавая экземпляр родительского класса, а вместо этого предоставив фабричный метод, который создает экземпляр некоторого (возможного частного) подкласса, имеющего реализацию по умолчанию:

родовое слово

Вы не можете написать код new Base() сейчас, но вы можете создать код Base.create(), чтобы получить реализацию по умолчанию.

Другие советы

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

Но один из способов сделать это - использовать шаблон стратегии , например:

родовое слово

Рассмотрите возможность создания интерфейса с помощью этого метода.Потомки класса должны будут это реализовать.

Я думаю, что самый простой способ - создать абстрактный класс, унаследованный от базового класса:

родовое слово

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

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

родовое слово

Есть причина , что это невозможно!

Производный класс может просто вызвать реализацию базового класса при переопределении метода.

Так какой смысл заставлять класс переопределять ваш метод?Думаю, пользы нет.

Ответом будет отрицательный.Вы можете изменить дизайн, используя шаблон дизайна.Это может вам помочь.

В качестве альтернативы вы можете заставить свои дочерние классы реализовать интерфейс.Интерфейс может быть реализован суперклассом, а может и не реализован.

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

Технически базовый класс определил метод, но его нельзя использовать без переопределения метода.В таком случае я предпочитаю исключение времени выполнения, поскольку для них не требуется явный оператор throw.Пример следует

родовое слово

Обратной стороной является то, что это не препятствует созданию объектов Base;однако любой, кто попытается использовать один из методов «должен быть переопределен», вскоре обнаружит, что он должен был переопределить класс.

Хотя это решение хорошо соответствует описанию запроса, ваше приложение, вероятно, выиграет, если не потребует такого решения.Гораздо лучше избежать сбоев во время выполнения с помощью проверок компилятора, что и обеспечивает ключевое слово abstract.

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

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

Я могу придумать, что вы могли бы сделать. Для этого потребуется абстрактная база с запечатанной (окончательной для Javaheads) реализацией по умолчанию. Таким образом, существует базовая реализация метода, который легко доступен для использования, как если бы он был «базовым» классом, но чтобы определить другой класс для нового сценария, вы должны вернуться к абстрактному классу и таким образом, вынуждены заново реализовать метод. Этот метод может быть единственным абстрактным элементом в классе, тем самым позволяя вам использовать базовые реализации других методов:

родовое слово

Однако у этого есть два недостатка. Во-первых, поскольку у вас нет доступа к реализации DefaultClass через наследование, вы не можете расширить реализацию DefaultClass, а это означает, что для выполнения того, что делает DefaultClass, плюс немного большего, вы должны переписать код из DefaultClass, нарушая DRY. Во-вторых, это работает только для одного уровня наследования, потому что вы не можете принудительно переопределить, если вы разрешаете наследование от DerivedClass.

может быть это поможет:

родовое слово

Хорошо, давайте изучим это так.Я придерживаюсь рекомендаций по стилю java и использую синтаксис java.Поэтому предполагается, что множественное наследование и шаблоны C ++ недоступны.

делать абстрактный метод родительского класса не обязательно, в ООП вы используете концепцию полиморфизма.вы можете использовать один и тот же метод двумя или более разными способами. Это называется переопределением метода.

Возьмем пример.

родовое слово

будет напечатано «мяуууу !!!»на экране.

но это не означает, что метод makeSound должен быть переопределен в дочернем классе.

Если вам нужно, чтобы дочерний класс был вынужден переопределить методы, вам лучше реализовать интерфейс этим классом.

родовое слово

при этом также будет напечатано «мяуууу !!!»на экране

Это может быть не рекомендуется, но вы можете использовать исключение (что-то вроде MethodeMustBeOverRiddenExp) в своей реализации метода. Конечно, это форсирование RunTime, но может быть лучше, чем чокнутый.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top