При переопределении метода, почему я могу увеличить доступ, но не уменьшить его?
47894 просмотра
7 ответа
Почему Java указывает, что спецификатор доступа для переопределенного метода может разрешить больший, но не меньший доступ, чем переопределенный метод? Например, метод защищенного экземпляра в суперклассе может быть сделан открытым, но не приватным, в подклассе.
Автор: yesilupper Источник Размещён: 12.11.2019 09:44Ответы (7)
69 плюса
Это фундаментальный принцип в ООП: дочерний класс является полноценным экземпляром родительского класса и поэтому должен представлять как минимум тот же интерфейс, что и родительский класс. Делать защищенные / общественные вещи менее заметными нарушит эту идею; вы можете сделать дочерние классы непригодными в качестве экземпляров родительского класса.
Автор: Patrick87 Размещён: 27.07.2011 09:4934 плюса
Представьте себе эти два класса:
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:489 плюса
Возьмите пример, приведенный ниже
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
8 плюса
Потому что это было бы странно
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
4 плюса
Поздно к вечеринке, но я хотел бы добавить еще одну проблему, связанную с переопределением: метод переопределения должен разрешать меньшее (или тот же уровень) выбрасываемое исключение, чем переопределенный метод; даже ничего не бросаемо вообще.
Принцип замещения Лискова может объяснить это тоже:
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:180 плюса
Поскольку подкласс является специализацией суперкласса, или, другими словами, это расширение суперкласса.
Представьте себе, например, метод toString. Все объекты Java имеют его, потому что он есть у класса Object. Представьте, что вы можете определить класс с помощью метода toString private. Вы больше не будете относиться ко всем объектам одинаково. Например, вы больше не сможете безопасно это сделать:
for (Object obj : collection) System.out.println(obj);
0 плюса
Что касается конкретного случая, который вы упомянули, как именно Java справится с этим? Если подкласс сделал открытый / защищенный метод частным, то что должна делать JVM, когда этот метод вызывается для экземпляра подкласса? Почитать приват и вызвать реализацию суперкласса? Кроме того, вы нарушаете контракт, указанный суперклассом, когда неожиданно говорите, что «никто не может получить доступ к этому методу, несмотря на то, что изначально было сказано в контракте».
Автор: Marvo Размещён: 27.07.2011 09:49Вопросы из категории :
- java В чем разница между int и Integer в Java и C #?
- java Как я могу определить IP моего маршрутизатора / шлюза в Java?
- java Каков наилучший способ проверки XML-файла по сравнению с XSD-файлом?
- java Как округлить результат целочисленного деления?
- java Преобразование списка <Integer> в список <String>
- java Почему я не могу объявить статические методы в интерфейсе?
- inheritance Предпочитаете композицию наследству?
- inheritance Вызывать события C # извне класса-владельца?
- inheritance Хорошие причины запретить наследование в Java?
- inheritance Что «супер» делает в Python?
- inheritance Наследование Python - как отключить функцию
- inheritance Переопределить метод с помощью общих параметров в Java?
- access-modifiers В чем разница между общедоступным, защищенным, частным и частным в Java?
- access-modifiers Почему я не могу иметь защищенных членов интерфейса?
- access-modifiers Почему я не могу получить доступ к членам, защищенным в C #, кроме как так?
- access-modifiers В чем разница между «защищенным» и «защищенным внутренним»?
- access-modifiers В C #, в чем разница между публичным, приватным, защищенным и не имеющим модификатора доступа?
- access-modifiers Лучшие практики модификаторов доступа в C # против Java