Почему Java не позволяет переопределять статические методы? - PullRequest
497 голосов
/ 08 февраля 2010

Почему невозможно переопределить статические методы?

Если возможно, пожалуйста, используйте пример.

Ответы [ 22 ]

4 голосов
/ 20 февраля 2013

Переопределив, мы можем создать полиморфную природу в зависимости от типа объекта. Статический метод не имеет отношения к объекту. Так что Java не может поддерживать переопределение статического метода.

4 голосов
/ 08 февраля 2010
Переопределение

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

4 голосов
/ 08 февраля 2010

В общем случае не имеет смысла разрешать «переопределение» статических методов, поскольку не было бы хорошего способа определить, какой из них вызывать во время выполнения. Если взять пример Employee, если мы вызовем RegularEmployee.getBonusMultiplier () - какой метод должен быть выполнен?

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

2 голосов
/ 29 июня 2015

Ответ на этот вопрос прост: метод или переменная, помеченная как статическая, принадлежит только классу, поэтому статический метод нельзя наследовать в подклассе, поскольку он принадлежит только суперклассу.

2 голосов
/ 04 сентября 2014

Переопределение в Java просто означает, что конкретный метод будет вызываться в зависимости от типа среды выполнения. объекта, а не его тип во время компиляции (что имеет место с переопределенными статическими методами). Так как статические методы являются методами класса, они не являются методами экземпляра, поэтому они не имеют никакого отношения к тому факту, какая ссылка указывает на какой объект или экземпляр, поскольку из-за природы статического метода он принадлежит определенному классу. Вы можете переопределить его в подклассе, но этот подкласс не будет ничего знать о статических методах родительского класса, потому что, как я уже сказал, он специфичен только для того класса, в котором он был объявлен. Доступ к ним с использованием ссылок на объекты - это просто дополнительная свобода, предоставляемая разработчиками Java, и мы, конечно, не должны думать о том, чтобы прекращать эту практику только тогда, когда они ограничивают ее. подробнее и пример http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html

2 голосов
/ 12 декабря 2013

Переопределив, вы получаете динамический полиморфизм. Когда вы говорите о переопределении статических методов, слова, которые вы пытаетесь использовать, противоречивы.

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

Динамическое полиморфное поведение возникает, когда программист использует объект и обращается к методу экземпляра. JRE отобразит разные методы экземпляров разных классов в зависимости от того, какой тип объекта вы используете.

Когда вы говорите о переопределении статических методов, мы обращаемся к статическим методам, используя имя класса, которое будет связано во время компиляции, поэтому нет понятия связывания методов во время выполнения со статическими методами. Таким образом, сам термин «переопределение» статических методов не имеет никакого значения.

Примечание: даже если вы обращаетесь к методу класса с помощью объекта, все равно java-компилятор достаточно умен, чтобы это выяснить, и будет выполнять статическое связывание.

1 голос
/ 12 сентября 2016

Статический метод, переменная, блок или вложенный класс принадлежит всему классу , а не объекту.

Метод в Java используется для представления поведения объекта / класса. Здесь, так как метод static (то есть статический метод используется для представления поведения только класса.) изменение / переопределение поведение всего класса будет нарушать явление одного фундаментальной основы объектно-ориентированного программирования, т. е. высокая когезия . (помните, что конструктор - это особый метод в Java.)

Высокая сплоченность - Один класс должен иметь только одну роль. Например: автомобильный класс должен производить только автомобильные объекты, а не велосипед, грузовики, самолеты и т. Д. Но у автомобильного класса могут быть некоторые особенности (поведение), которые принадлежат только ему самому.

Поэтому при разработке языка программирования Java. Разработчики языка решили позволить разработчикам сохранять некоторые поведения класса при себе, делая метод статичным по своей природе.


Приведенный ниже фрагмент кода пытается переопределить статический метод, но не столкнется с какой-либо ошибкой компиляции.

public class Vehicle {
static int VIN;

public static int getVehileNumber() {
    return VIN;
}}

class Car extends Vehicle {
static int carNumber;

public static int getVehileNumber() {
    return carNumber;
}}

Это потому, что здесь мы не переопределяем метод, а просто повторно объявляем его. Java допускает повторное объявление метода (статический / нестатический).

Удаление статического ключевого слова из метода getVehileNumber () класса Car приведет к ошибке компиляции, поскольку мы пытаемся изменить функциональность статического метода, который относится только к классу Vehicle.

Кроме того, если getVehileNumber () объявлен как final , то код не будет компилироваться, поскольку ключевое слово final ограничивает программиста от повторного объявления метода.

public static final int getVehileNumber() {
return VIN;     }

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

1 голос
/ 27 мая 2016

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

1 голос
/ 28 марта 2014

Простое решение: использовать экземпляр Singleton. Это позволит переопределения и наследования.

В моей системе есть класс SingletonsRegistry, который возвращает экземпляр для переданного класса. Если экземпляр не найден, он создается.

Класс языка Haxe:

package rflib.common.utils;
import haxe.ds.ObjectMap;



class SingletonsRegistry
{
  public static var instances:Map<Class<Dynamic>, Dynamic>;

  static function __init__()
  {
    StaticsInitializer.addCallback(SingletonsRegistry, function()
    {
      instances = null;
    });

  } 

  public static function getInstance(cls:Class<Dynamic>, ?args:Array<Dynamic>)
  {
    if (instances == null) {
      instances = untyped new ObjectMap<Dynamic, Dynamic>();      
    }

    if (!instances.exists(cls)) 
    {
      if (args == null) args = [];
      instances.set(cls, Type.createInstance(cls, args));
    }

    return instances.get(cls);
  }


  public static function validate(inst:Dynamic, cls:Class<Dynamic>)
  {
    if (instances == null) return;

    var inst2 = instances[cls];
    if (inst2 != null && inst != inst2) throw "Can\'t create multiple instances of " + Type.getClassName(cls) + " - it's singleton!";
  }

}
1 голос
/ 08 февраля 2010

Какая польза от переопределения статических методов. Вы не можете вызывать статические методы через экземпляр.

MyClass.static1()
MySubClass.static1()   // If you overrode, you have to call it through MySubClass anyway.

РЕДАКТИРОВАТЬ: кажется, что из-за неудачного упущения в дизайне языка, вы можете вызывать статические методы через экземпляр. Обычно никто не делает это. Мой плохой.

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