При переопределении метода, почему я могу увеличить доступ, но не уменьшить его?

java inheritance access-modifiers

47894 просмотра

7 ответа

318 Репутация автора

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

Автор: yesilupper Источник Размещён: 27.07.2011 09:44

Ответы (7)


8 плюса

235815 Репутация автора

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

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's the same object!
Автор: Oliver Charlesworth Размещён: 27.07.2011 09:47

34 плюса

33768 Репутация автора

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

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 . Поэтому невозможно сделать вещи менее заметными на подклассах, так как, получив ссылку на суперкласс, вы сможете получить доступ к этому материалу.

Автор: Maurício Linhares Размещён: 27.07.2011 09:48

0 плюса

1031 Репутация автора

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

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

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

Автор: João Fernandes Размещён: 27.07.2011 09:48

69 плюса

20107 Репутация автора

Решение

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

Автор: Patrick87 Размещён: 27.07.2011 09:49

0 плюса

14288 Репутация автора

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

Автор: Marvo Размещён: 27.07.2011 09:49

9 плюса

1357 Репутация автора

Возьмите пример, приведенный ниже

 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

Автор: Vineeth Bhaskaran Размещён: 13.11.2013 11:04

4 плюса

720 Репутация автора

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

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

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 (или необходима скорая помощь)

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

Автор: U and me Размещён: 30.04.2016 08:18
Вопросы из категории :
32x32