Подтвердить что ты не робот

Модификаторы доступа к Java и методы переопределения

Почему Java указывает, что спецификатор доступа для метода переопределения может предоставить больше, но не менее, доступ, чем переопределенный метод? Например, метод защищенного экземпляра в суперклассе может быть общедоступным, но не закрытым, в подклассе.

4b9b3361

Ответ 1

Это фундаментальный принцип в ООП: дочерний класс является полноправным экземпляром родительского класса и поэтому должен содержать по крайней мере тот же интерфейс, что и родительский класс. Сделать менее видимыми защищенные/общественные вещи нарушат эту идею; вы могли бы сделать дочерние классы непригодными для использования в качестве экземпляров родительского класса.

Ответ 2

Представьте себе эти два класса:

public class Animal {
  public String getName() { return this.name; }
}

public class Lion extends Animal {
  private String getName() { return this.name; }
}

Я мог бы написать этот код:

Animal lion = new Lion();
System.out.println( lion.getName() );

И он должен быть действительным, поскольку в Animal метод getName() является общедоступным, даже если он был закрыт в Lion > . Таким образом, невозможно сделать вещи менее заметными на подклассах, как только у вас есть ссылка на суперкласс, с которой вы могли бы получить доступ к этому материалу.

Ответ 3

Потому что это было бы странно:

class A {
    public void blah() {}
}

class B extends A {
    private void blah() {}
}


B b = new B();
A a = b;
b.blah();  // Can't do it!
a.blah();  // Can do it, even though it the same object!

Ответ 4

Приведите пример ниже

 class Person{
 public void display(){
      //some operation
    }
 }

class Employee extends Person{
   private void display(){
       //some operation
   }
 }

Типичное переопределение происходит в следующем случае

Person p=new Employee();

Здесь p - ссылка на объект с типом Person (суперкласс), когда мы вызываем p.display(). Поскольку модификатор доступа более ограничительный, ссылка объекта p не может получить доступ к дочернему объекту типа Employee

Ответ 5

Поздно к стороне, но я хотел бы добавить еще одну проблему, связанную с переопределением: метод переопределения должен допускать исключение (или одинаковый уровень) исключаемого исключения, чем переопределенный метод; даже ничего не подбрасываемое вообще.

Принцип подстановки Лискова также может объяснить это:

interface Actionable {
  void action() throws DislocationException;
}

public class Actor implements Actionable {
  @Override 
  public void action() throws DislocationException {
     //....
  }
} 

public class Stuntman implements Actionable {
  @Override // this will cause compiler error
  public void action() throws DislocationException, DeathException {
     //....
  }
}

// legacy code to use Actionable
try {
   Actionable actor = new Actor(); // this cannot be replaced by a Stuntman, 
                                   // or it may break the try/catch block
   actor.action();
} catch (DislocationException exc) {
   // Do something else
}

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

Я часто вызываю правило переопределения "[может быть] больше доступа [уровень], [но] меньше исключений"

Ответ 6

Поскольку подкласс является специализацией суперкласса, или, другими словами, он является расширением суперкласса.

Представьте, например, метод toString. Все объекты Java имеют это, потому что объект класса имеет его. Представьте, что вы можете определить класс с помощью метода toString private. Затем вы больше не относитесь ко всем объектам одинаково. Например, вы уже не сможете это безопасно:

for (Object obj : collection) System.out.println(obj);

Ответ 7

Хорошо, с точки зрения конкретного случая, о котором вы говорили, как именно Java справится с этим? Если подкласс сделал открытый/защищенный метод приватным, то что должен делать JVM, когда этот метод вызывается в экземпляре подкласса? Почитайте частные и вызывают реализацию суперкласса? Кроме того, вы нарушаете контракт, указанный суперклассом, когда вы вдруг говорите: "Никто не может получить доступ к этому методу, несмотря на то, что контракт первоначально сказал".