Вопрос в Java, почему я не могу определить абстрактный статический метод? например
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
java
abstract-class
static-methods
hhafez
источник
источник
Ответы:
Потому что «абстрактный» означает: «не реализует никакой функциональности», а «статический» означает: «есть функциональность, даже если у вас нет экземпляра объекта». И это логическое противоречие.
источник
abstract static
это имело бы смысл. Это был бы метод самого объекта класса, который должны реализовывать объекты подкласса. Конечно, как обстоят дела, твой ответ верен, несмотря на мои разговоры о языке.abstract static
: функция X, которая «реализована в подклассе», не может одновременно «выполняться в классе» - только в подклассе . Где это тогда уже не абстрактно.static
не означает «не пустой» - это просто следствие того, что Java не позволяет статическим методам быть абстрактными. Это означает «вызываемый в классе». (Это должно означать «вызываемый только в классе», но это другая проблема.) Если бы Java поддерживалabstract static
методы, я ожидал бы, что это означает, что метод 1) должен быть реализован подклассами, а 2) является методом класса подкласса. Некоторые методы просто не имеют смысла как методы экземпляра. К сожалению, Java не позволяет вам указать это при создании абстрактного базового класса (или интерфейса).Плохой языковой дизайн. Было бы гораздо эффективнее напрямую вызывать статический абстрактный метод, чем создавать экземпляр только для использования этого абстрактного метода. Особенно актуально при использовании абстрактного класса в качестве обходного пути для невозможности расширения перечисления, что является еще одним плохим примером проектирования. Надеюсь, что они решат эти ограничения в следующем выпуске.
источник
static
себя уже является нарушением ....Вы не можете переопределить статический метод, поэтому делать его абстрактным было бы бессмысленно. Более того, статический метод в абстрактном классе должен принадлежать этому классу, а не переопределяющему классу, поэтому его нельзя использовать в любом случае.
источник
abstract
Аннотации к способу указывает на то, что этот метод должен быть переопределен в подклассе.В Java
static
элемент (метод или поле) не может быть переопределен подклассами (это не обязательно верно в других объектно-ориентированных языках, см. SmallTalk.) Элементstatic
может быть скрыт , но это принципиально отличается от переопределенного .Поскольку статические члены не могут быть переопределены в подклассе,
abstract
аннотация к ним не может быть применена.Кроме того, другие языки поддерживают статическое наследование, как и наследование экземпляров. С точки зрения синтаксиса, эти языки обычно требуют, чтобы имя класса было включено в оператор. Например, в Java, если вы пишете код в ClassA, это эквивалентные операторы (если methodA () является статическим методом, и нет метода экземпляра с такой же сигнатурой):
а также
В SmallTalk имя класса не является обязательным, поэтому синтаксис (обратите внимание, что SmallTalk не использует. Для разделения «субъекта» и «глагола», а вместо этого использует его в качестве терминатора исправления состояния):
Поскольку имя класса всегда требуется, правильная «версия» метода всегда может быть определена путем обхода иерархии классов. Что бы это ни стоило, я иногда пропускаю
static
наследование, и меня укусило отсутствие статического наследования в Java, когда я впервые начал с ним. Кроме того, SmallTalk типизирован по типу утки (и поэтому не поддерживает программу по контракту.) Таким образом, он не имеетabstract
модификатора для членов класса.источник
Я тоже задавал тот же вопрос, вот почему
Так как абстрактный класс говорит, он не даст реализацию и позволит подклассу давать его
поэтому подкласс должен переопределить методы суперкласса,
ПРАВИЛО № 1 - Статический метод не может быть переопределен
Поскольку статические члены и методы являются элементами времени компиляции, поэтому допускается перегрузка (полиморфизм времени компиляции) статических методов, а не переопределение (полиморфизм времени выполнения)
Таким образом, они не могут быть абстрактными.
Нет такой вещи, как абстрактная статика <--- Не допускается в Java Universe
источник
abstract static
см. Stackoverflow.com/questions/370962/… . Реальная причина , почему Java не позволяет статические методы быть переопределены в том , что Java не позволяет статические методы быть переопределены.foo(String)
не то же самое,foo(Integer)
что и все.Это ужасный языковой дизайн и на самом деле нет причин, почему это невозможно.
На самом деле, здесь есть реализация того, как это МОЖЕТ быть сделано в JAVA :
================= Старый пример ниже =================
Ищите getRequest, и можно вызвать getRequestImpl ... setInstance, чтобы изменить реализацию до вызова.
Используется следующим образом:
источник
abstract static
метода, который был задан в вопросе, и вы написали жирным шрифтом МОЖНО СДЕЛАТЬ В ЯВА . Это полностью вводит в заблуждение.Абстрактный метод определяется только для того, чтобы его можно было переопределить в подклассе. Однако статические методы не могут быть переопределены. Следовательно, ошибка времени компиляции - иметь абстрактный статический метод.
Теперь следующий вопрос: почему статические методы нельзя переопределить?
Это потому, что статические методы принадлежат определенному классу, а не его экземпляру. Если вы попытаетесь переопределить статический метод, вы не получите никакой ошибки компиляции или времени выполнения, но компилятор просто скроет статический метод суперкласса.
источник
Статический метод по определению не должен знать
this
. Таким образом, это не может быть виртуальный метод (который перегружен в соответствии с информацией динамического подкласса, доступной черезthis
); вместо этого перегрузка статического метода основана исключительно на информации, доступной во время компиляции (это означает: как только вы ссылаетесь на статический метод суперкласса, вы вызываете именно метод суперкласса, но никогда не метод подкласса).В соответствии с этим, абстрактные статические методы были бы совершенно бесполезны, потому что вы никогда не будете заменять их ссылку каким-либо определенным телом.
источник
Я вижу, что ответы на этот вопрос уже есть, но я не вижу практических решений. Конечно, это реальная проблема, и нет веских причин для исключения этого синтаксиса в Java. Поскольку в исходном вопросе отсутствует контекст, в котором это может понадобиться, я предоставляю и контекст, и решение:
Предположим, у вас есть статический метод в группе классов, которые идентичны. Эти методы вызывают статический метод, специфичный для класса:
doWork()
методыC1
иC2
идентичны. Может быть много таких calsses:C3
C4
и т.д. Если бы этоstatic abstract
было разрешено, вы бы удалили дублирующийся код, выполнив что-то вроде:но это не скомпилируется, потому что
static abstract
комбинация не допускается. Однако это можно обойти с помощьюstatic class
конструкции, которая допускает:С этим решением единственный дублирующийся код
источник
C1.doWork()
илиC2.doWork()
Но вы не можете позвонитьC.doWork()
. Также в приведенном вами примере, который не сработает, предположим, если это было разрешено, то как классC
найдет реализациюdoMoreWork()
? Наконец, я бы назвал ваш контекстный код плохим дизайном. Почему? просто потому, что вы создали отдельную функцию для кода, который является уникальным, вместо того, чтобы создать функцию для кода, который является общим, и затем реализовать статическую функцию в классеC
. Это проще !!!Предположим, есть два класса,
Parent
иChild
.Parent
естьabstract
. Заявления следующие:Это означает, что любой экземпляр
Parent
должен указывать, какrun()
выполняется.Однако предположим, что
Parent
это не такabstract
.Это означает, что
Parent.run()
будет выполняться статический метод.Определение
abstract
метода - «Метод, который объявлен, но не реализован», что означает, что он сам ничего не возвращает.Определение
static
метода: «Метод, который возвращает одно и то же значение для тех же параметров независимо от экземпляра, в котором он вызывается».An
abstract
возвращаемого значения метода будет меняться по мере изменения экземпляра.static
Метод не будет.static abstract
Метод в значительной степени способ , при котором возвращаемое значение является постоянным, но не возвращает ничего. Это логическое противоречие.Кроме того, для
static abstract
метода нет особой причины .источник
Абстрактный класс не может иметь статический метод, потому что абстракция выполняется для достижения ДИНАМИЧНОЙ СВЯЗИ, в то время как статические методы статически связаны с их функциональностью. Статический метод означает поведение, не зависящее от переменной экземпляра, поэтому экземпляр / объект не требуется. Просто класс. Статические методы принадлежат классу, а не объекту. Они хранятся в области памяти, известной как PERMGEN, откуда она используется для каждого объекта. Методы в абстрактном классе динамически связаны с их функциональностью.
источник
Объявление метода как
static
означает, что мы можем вызвать этот метод по имени класса, и, если этот классabstract
также, нет смысла вызывать его, так как он не содержит никакого тела, и, следовательно, мы не можем объявить метод какstatic
иabstract
.источник
Поскольку абстрактные методы принадлежат классу и не могут быть переопределены реализующим классом. Даже если есть статический метод с такой же сигнатурой, он скрывает метод, но не переопределяет его. Поэтому несущественно объявлять абстрактный метод статическим, так как он никогда не получит тело. Таким образом, ошибка времени компиляции.
источник
Статический метод может быть вызван без экземпляра класса. В вашем примере вы можете вызвать foo.bar2 (), но не foo.bar (), потому что для bar вам нужен экземпляр. Следующий код будет работать:
Если вы вызываете статический метод, он всегда будет выполняться с одним и тем же кодом. В приведенном выше примере, даже если вы переопределите bar2 в ImplementsFoo, вызов var.bar2 () выполнит foo.bar2 ().
Если bar2 теперь не имеет реализации (это означает абстрактное значение), вы можете вызвать метод без реализации. Это очень вредно.
источник
Я считаю, что нашел ответ на этот вопрос в форме того, почему методы интерфейса (которые работают как абстрактные методы в родительском классе) не могут быть статичными. Вот полный ответ (не мой)
В основном статические методы могут быть связаны во время компиляции, так как для их вызова вам нужно указать класс. Это отличается от методов экземпляра, для которых класс ссылки, из которой вы вызываете метод, может быть неизвестен во время компиляции (таким образом, какой вызываемый блок кода может быть определен только во время выполнения).
Если вы вызываете статический метод, вы уже знаете класс, в котором он реализован, или любые его прямые подклассы. Если вы определите
Тогда любой
Foo.bar();
вызов, очевидно, является незаконным, и вы всегда будете использоватьFoo2.bar();
.Имея это в виду, единственная цель статического абстрактного метода состояла бы в том, чтобы заставить подклассы реализовать такой метод. Сначала вы можете подумать, что это ОЧЕНЬ неправильно, но если у вас есть параметр общего типа,
<E extends MySuperClass>
было бы неплохо гарантировать через интерфейс, которыйE
может.doSomething()
. Имейте в виду, что из-за стирания типов дженерики существуют только во время компиляции.Так будет ли это полезно? Да, и, возможно, именно поэтому Java 8 допускает статические методы в интерфейсах (хотя только с реализацией по умолчанию). Почему бы не абстрагировать статические методы с реализацией по умолчанию в классах? Просто потому, что абстрактный метод с реализацией по умолчанию на самом деле является конкретным методом.
Почему бы не абстрактные / интерфейсные статические методы без реализации по умолчанию? По-видимому, просто из-за того, как Java определяет, какой блок кода он должен выполнить (первая часть моего ответа).
источник
Поскольку абстрактный класс является концепцией OOPS, а статические члены не являются частью OOPS ....
Теперь мы можем объявить статические методы завершения в интерфейсе и выполнить интерфейс, объявив метод main внутри интерфейса.
источник
Идея иметь абстрактный статический метод состояла бы в том, что вы не можете использовать этот конкретный абстрактный класс непосредственно для этого метода, но только первая производная будет иметь возможность реализовать этот статический метод (или для обобщений: фактический класс обобщенного вами использование).
Таким образом, вы можете создать, например, абстрактный класс sortableObject или даже интерфейс с (авто) абстрактными статическими методами, который определяет параметры опций сортировки:
Теперь вы можете определить сортируемый объект, который можно отсортировать по основным типам, которые одинаковы для всех этих объектов:
Теперь вы можете создать
который может извлекать типы, создавать всплывающее меню для выбора типа для сортировки и прибегать к списку, получая данные из этого типа, а также иметь функцию добавления, которая при выборе типа сортировки может автоматически -сортировать новые элементы в. Обратите внимание, что экземпляр SortableList может напрямую обращаться к статическому методу «T»:
Проблема с необходимостью использования экземпляра состоит в том, что в SortableList, возможно, еще нет элементов, но уже требуется обеспечить предпочтительную сортировку.
Привет, Олаф.
источник
Во-первых, ключевой момент в отношении абстрактных классов - абстрактный класс не может быть создан (см. Вики ). Таким образом, вы не можете создать любой экземпляр абстрактного класса.
Теперь способ, которым java работает со статическими методами, заключается в совместном использовании метода со всеми экземплярами этого класса.
Итак, если вы не можете создать экземпляр класса, этот класс не может иметь абстрактные статические методы, так как абстрактный метод требует расширения.
Boom.
источник
Согласно документу Java :
В Java 8 наряду со стандартными методами в интерфейсе также разрешены статические методы. Это облегчает нам организацию вспомогательных методов в наших библиотеках. Мы можем хранить статические методы, специфичные для интерфейса, в одном интерфейсе, а не в отдельном классе.
Хороший пример этого:
вместо
Другой пример использования статических методов также приведен в самом документе :
источник
Потому что «абстрактный» означает, что метод предназначен для переопределения, и нельзя переопределять «статические» методы.
источник
Обычные методы могут быть абстрактными, если они должны быть переопределены подклассами и снабжены функциональностью. Представьте, что класс
Foo
расширен иBar1, Bar2, Bar3
т. Д. Итак, у каждого будет своя версия абстрактного класса в соответствии со своими потребностями.Теперь статические методы по определению принадлежат классу, они не имеют ничего общего с объектами класса или объектами его подклассов. Им даже не нужно, чтобы они существовали, их можно использовать без создания экземпляров классов. Следовательно, они должны быть готовы к работе и не могут зависеть от подклассов для добавления к ним функциональности.
источник
Потому что абстрактный - это ключевое слово, которое применяется к абстрактным методам, но не определяет тело. И если говорить о статическом ключевом слове, то оно относится к области классов.
источник
потому что если вы используете какой-либо статический член или статическую переменную в классе, он будет загружаться во время загрузки класса.
источник
Вы можете сделать это с помощью интерфейсов в Java 8.
Это официальная документация об этом:
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
источник
Потому что, если класс расширяет абстрактный класс, он должен переопределять абстрактные методы, и это обязательно. А поскольку статические методы являются методами класса, разрешаемыми во время компиляции, тогда как переопределенные методы являются методами экземпляра, разрешенными во время выполнения и после динамического полиморфизма.
источник