Почему статические методы не могут быть абстрактными в Java?
Вопрос в том, почему в Java я не могу определить абстрактный статический метод? Например:
abstract class foo {
abstract void bar(); // <-- это допустимо
abstract static void bar2(); // <-- это недопустимо. Почему так?
5 ответ(ов)
Слово "abstract" означает "не реализует функциональности", тогда как "static" подразумевает, что функциональность существует, даже если у вас нет экземпляра объекта. Это логическое противоречие.
Плохой дизайн языка. Было бы гораздо эффективнее вызывать непосредственно статический абстрактный метод, чем создавать экземпляр только для использования этого абстрактного метода. Особенно это касается случаев, когда абстрактный класс используется как обходной путь для того, чтобы не иметь возможности расширять перечисления (enum), что также является примером плохого дизайна. Надеюсь, они исправят эти ограничения в следующем релизе.
Вы не можете переопределить статический метод, поэтому делать его абстрактным было бы бессмысленно. Более того, статический метод в абстрактном классе будет принадлежать именно этому классу, а не классу-наследнику, поэтому его нельзя будет использовать в классе-наследнике.
Аннотация abstract
для метода указывает на то, что этот метод ДОЛЖЕН быть переопределен в подклассе.
В Java статические члены (методы или поля) не могут быть переопределены в подклассах (это не всегда верно для других объектно-ориентированных языков, например, SmallTalk). Статические члены могут быть скрыты, но это принципиально отличается от переопределения.
Поскольку статические члены не могут быть переопределены в подклассе, аннотация abstract
не может быть применена к ним.
В качестве побочного замечания - в других языках поддерживается статическое наследование, так же как и наследование экземпляров. С точки зрения синтаксиса, такие языки обычно требуют указания имени класса в выражении. Например, в Java, если вы пишете код в классе ClassA, следующие выражения эквивалентны (при условии, что methodA() - это статический метод, и не существует метода экземпляра с такой же сигнатурой):
ClassA.methodA();
и
methodA();
В SmallTalk имя класса не является необязательным, поэтому синтаксис выглядит следующим образом (обратите внимание, что SmallTalk не использует точку для разделения "субъекта" и "глагола", а вместо этого использует ее в качестве терминатора выражения):
ClassA methodA.
Так как имя класса всегда требуется, правильная "версия" метода всегда может быть определена путем обхода иерархии классов. Что касается меня, я иногда скучаю по статическому наследованию и столкнулся с проблемами из-за его отсутствия в Java, когда только начинал с этим языком. Кроме того, SmallTalk использует динамическую типизацию (duck typing), а следовательно, не поддерживает контрактное программирование, так что у него нет модификатора abstract
для членов класса.
Я задавал тот же вопрос, и вот причина:
Поскольку абстрактный класс утверждает, что он не предоставляет реализацию и позволяет подклассу это делать, то подкласс обязан переопределять методы суперкласса.
ПРАВИЛО №1 - Статический метод не может быть переопределён.
Это связано с тем, что статические члены и методы являются элементами времени компиляции, поэтому перегрузка (полиморфизм на этапе компиляции) статических методов допустима, в то время как переопределение (полиморфизм на этапе выполнения) — нет.
Таким образом, статические методы не могут быть абстрактными.
Не существует понятия абстрактный статический ←-- Не допускается в мире Java.
Каков эквивалент статических методов Java в Kotlin?
Когда следует использовать статические методы
Что значит "Не удалось найти или загрузить основной класс"?
Что значит 'synchronized'?
Eclipse/Java: не работает автозавершение кода