Почему статические методы не могут быть абстрактными в Java?
Вопрос в том, почему в Java я не могу определить абстрактный статический метод? например
abstractclassfoo { abstractvoidbar( ); // <-- this is ok abstractstaticvoidbar2(); //<-- this isn't why? }
Переведено автоматически
Ответ 1
Потому что "абстрактный" означает: "Не реализует никакой функциональности", а "статический" означает: "Функциональность есть, даже если у вас нет экземпляра объекта". И это логическое противоречие.
Ответ 2
Плохой дизайн языка. Было бы гораздо эффективнее вызвать статический абстрактный метод напрямую, чем создавать экземпляр только для использования этого абстрактного метода. Особенно это актуально при использовании абстрактного класса в качестве обходного пути для невозможности расширения enum, что является еще одним примером плохого дизайна. Надеюсь, они решат эти ограничения в следующем выпуске.
Ответ 3
Вы не можете переопределить статический метод, поэтому делать его абстрактным было бы бессмысленно. Более того, статический метод в абстрактном классе принадлежал бы этому классу, а не переопределяющему классу, поэтому его все равно нельзя было бы использовать.
Ответ 4
В abstract аннотации к методу указывается, что метод ДОЛЖЕН быть переопределен в подклассе.
В Java static элемент (метод или поле) не может быть переопределен подклассами (это не обязательно верно в других объектно-ориентированных языках, см. SmallTalk.). static Элемент может быть скрытым, но это принципиально отличается от переопределенного.
Поскольку статические члены не могут быть переопределены в подклассе, abstract аннотация не может быть применена к ним.
Кстати, другие языки поддерживают статическое наследование, точно так же, как наследование экземпляров. С точки зрения синтаксиса, эти языки обычно требуют, чтобы имя класса включалось в инструкцию. Например, в Java, предполагая, что вы пишете код в ClassA , это эквивалентные операторы (если methodA() является статическим методом, и нет метода экземпляра с такой же сигнатурой):
ClassA.methodA();
и
methodA();
В SmallTalk имя класса не является необязательным, поэтому синтаксис такой (обратите внимание, что SmallTalk не использует . чтобы разделить "подлежащее" и "глагол", но вместо этого использует его в качестве ограничителя statemend):
ClassA methodA.
Поскольку имя класса всегда обязательно, правильную "версию" метода всегда можно определить путем обхода иерархии классов. Как бы то ни было, я иногда пропускаю static наследование, и был поражен отсутствием статического наследования в Java, когда я впервые начал с этим работать. Кроме того, SmallTalk имеет утиный тип (и, следовательно, не поддерживает программу по контракту.) Таким образом, у него нет abstract модификатора для членов класса.