2015-09-24 6 views
0

Рассмотрим следующий пример:Почему для экземпляра родительского класса допускается создание экземпляра родительского класса с помощью конструктора дочернего класса?

public class parent { 
    int x; 

    parent() { 
     x = 5; 
    } 

} 

public class child extends parent { 
int y; 

child() { 
    super(); 
    y = 10; 
} 

public static void main(String[] args) { 

    parent p = new child(); 
    System.out.println(p.y);//can't access variable y 
} 

}

Вот конструктор дочерний класс в настоящее время называется на объект родительского класса. Я часто сталкивался с этой ситуацией при программировании на Android. Мой вопрос: почему это разрешено? Конструктор дочернего класса может инициализировать дополнительные элементы, но их проект не может быть определен в родительском классе, как в приведенном выше случае.

+0

Подсказка: какой тип объекта 'p' и его базовый тип? следующий 'y' объявляется в классе' child'. – Satya

+0

«Здесь конструктор дочернего класса вызывается на объект родительского класса». - нет, вы определяете объект, который имеет тип 'child', но остальная часть вашего кода видит его как объект' parent'. – Smutje

+0

Надеюсь, у вас есть словарь, в котором вы можете найти «расширить». В этом контексте ('child extends parent') это означает, что у дочернего класса есть весь родительский класс, плюс некоторые поля и методы. – laune

ответ

10

Почему для объекта родительского класса создается экземпляр с использованием конструктора дочернего класса?

Это не то, что там происходит. В этой строке:

parent p = new child(); 

... вы создаете child объект, а не parent объекта. Переменная, которую вы используете для ссылки на нее, p, имеет тип parent, что означает, что вы можете использовать только parent через эту ссылку, но объект является объектом child. Объект у есть y, вы просто не можете получить к нему доступ через p. Вы можете видеть, что, делая это:

parent p = new child(); 
System.out.println(((child)p).y); 

Рассказывая компилятор мы знаем, что p относится к child даже если это типа parent (через «слепок»), мы можем получить доступ к child Определённые ее части , (Это не очень хорошая практика, когда у вас есть альтернатива.)

Эта способность для разницы (внутри ограничений) между ссылкой, которую вы имеете чему-то, и тем, что она на самом деле называется «полиморфизмом» (с использованием нескольких форм) и является центральным элементом объектно-ориентированного программирования.

Рассмотрим:

class Animal { 
} 

class Dog extends Animal { 
} 

class Cat extends Animal { 
} 

Все Dog s являются Animal s, как и все Cat s, но Dog s не Cat s. Предположим, что вы зоомагазин и хотите хранить список животных, у вас есть под рукой:

List<Animal> animals; 

Записи могут быть объектами типа Animalили любой из его подтипов, такие как Dog и Cat. Это позволяет вам иметь общие аспекты животных на Animal, а затем только Dog - или Cat - конкретные аспекты (свойства или поведение) на этих типах. Вы можете пропустить свой список Animal s, действующий на их животное, не беспокоясь о том, являются ли они Dog s или Cat s.

0

Поскольку ребенок является родителем тоже. Таким образом, он может рекламировать свой тип. Но объектом будет ребенок. Итак, объект Child типа Parent.

Примечание: Названия классов имеют прописные буквы.

2

Не существует экземпляра родительского класса, за исключением того, что он является частью экземпляра child в конструкторе. Здесь вы получаете один экземпляр, и это пример child.

Допускается присвоение parent p, поскольку каждый объект child также является объектом parent.

Назначение объекта child объекту переменной с типом родительского объекта позволяет запрограммировать интерфейс этого класса, ограничивая использование класса методам его родительского элемента. Это дает вам возможность изменить реализацию позже:

Parent p = new OtherChild(); 

Таким образом, код, который использует p не нужно знать, что он обращается к Child или OtherChild объект.

0

Когда вы пишете , он фактически создает объект дочернего класса. Когда он вызывает конструктор дочерних классов, конструктор суперкласса сначала вызывается вызовом super().

Смежные вопросы