Допустим есть класс A
и наследуемый от него класс B
.
И у А
, и у B
есть метод get()
, который в первом случае возвращает переменную из класса А
, а во втором из класса B
. И есть ссылочная переменная ptr
класса A
.
Как будет работать такой код?
A ptr = new A();
ptr.get(); // это выполнится
ptr = new B(); // ссылочная переменная суперкласса может
// указывать на объект подкласса, если я все правильно понял.
ptr.get(); // тут будет вызван метод get() класса В
// т.к. ссылка на объект В.
// Но сам метод берет приватную переменную из объекта В.
// А суперкласс о ней не знает, и для него она не существует.".
Как это работает? Или я что-то не верно понял?
Определение переменной ptr
класса A
ограничивает доступные для объекта методы интерфейсом класса A
(перечнем методов с их параметрами и возвращаемыми значениями). Т.е. нельзя будет вызвать методы, добавленные в наследниках.
При переопределении метода C get()
в классе-наследнике B
мы имеем доступ ко всем приватным полям B
. При вызове метода будет возвращена копия ссылки на объект из приватного поля. При этом поле останется недоступным: обращение к приватному полю ptr.reference
не скомпилируется ни для суперкласса, ни для наследника.
Возьмём следующие классы:
class A {
private C reference=new C();
C get() {
return reference;
}
}
class B extends A {
private D reference=new D();
@Override
C get() {
return reference;
}
}
class C {}
class D extends C {}
Выполним следующий код:
A ptr=new A();
System.out.println(ptr.get() instanceof C);
ptr= new B();
System.out.println(ptr.get() instanceof C);
System.out.println(ptr.get() instanceof D);
Получим
true
true
true
Кстати, при переопределении метода в качестве возвращаемого значения можно использовать наследника класса из родительского определения, т.е. в классе B
можно написать D get()
. В данном примере результат не изменится.
Это полиморфизм, объект класса A
определяет только возвращаемый тип объекта (предоставляет интерфейс), а реализация полностью лежит в классе B
. Когда будет вызван метод get
по сути просто вызовется метода класса B
, а компилятор не будет ругаться, потому что сигнатура методов будет полностью совпадать.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Как в Java проверить деление на ноль? Пишу небольшой калькулятор и нужно вывести Toast об ошибке ,что нельзя делить число num1 на нольЧто-то я не соображаю...
В приложении для Андроид требуется строить блок схемы
Например у меня есть button1 - button 9, и хочу делать так, чтоб при нажатии на button1 рандомно нажимался например button 2, button 3 или button 4