Java 为什么子类是';存储在超类类型变量中时是否保留私有变量?
我肯定错过了一些基本的继承,因为它对我来说没有意义 鉴于这两类:Java 为什么子类是';存储在超类类型变量中时是否保留私有变量?,java,inheritance,subclass,superclass,Java,Inheritance,Subclass,Superclass,我肯定错过了一些基本的继承,因为它对我来说没有意义 鉴于这两类: class Person { private String name; } class Student extends Person { private String degree; } 为什么可以创建一个新的Student对象,将其存储在Person类型变量中,并且仍然能够保留变量字符串度并访问它 Person p = new Student("John", "Master's"); 我认为可以使用上面的初始化
class Person
{
private String name;
}
class Student extends Person
{
private String degree;
}
为什么可以创建一个新的Student
对象,将其存储在Person
类型变量中,并且仍然能够保留变量字符串度并访问它
Person p = new Student("John", "Master's");
我认为可以使用上面的初始化,因为p
除了name
之外没有任何变量,因为Person
变量不能包含degree
变量,因此它是合法的-但是当您这样做时,p
中不存在degree
这就是我所认为的原因,相反的事物是非法的
(Student s=newperson(“John”);
)-因为这样s
就不会初始化它的另一个变量(degree
)。具有超类型引用类型的变量可以包含子类型实例的引用。将子类型实例指定给变量不会以任何方式更改实例;它只是拓宽了参考的类型。所有实例数据仍然存在,并且可以通过向下转换进行检索。就是
Student s = new Student("John", "Master's");
Person p = s; // no cast needed for a widening conversion
与以下内容完全相同:
Person p = new Student("John", "Master's");
Student s = (Student) p; // cast required for a narrowing conversion
编辑也许这有助于澄清问题。
假设有第二个子类Person
:
class Teacher extends Person
{
private String department;
}
现在您可以执行以下操作:
Person p = new Teacher("Fred", "Physics");
Teacher t = (Teacher) p;
但如果您以后尝试这样做:
p = new Teacher("Fred", "Physics");
Student s = (Student) p; // Error!
您将得到一个,因为在程序中的这一点上,p
现在是对一个对象的引用(Teacher
),该对象不是Student
这里有一个类比。在英语中,你可能会说,“我有一只宠物动物”。这与动物的类型无关。(例如,你无法知道宠物是否会吠叫。)另一方面,如果你说“我有一只宠物狗”,那么问它是否会对陌生人吠叫是有道理的。关键是:称你的宠物为动物并不能改变它是(或不是)狗的事实。使用更通用(例如,基类)的引用类型来存储对象引用不会改变对象本身的性质。您失去了对对象细节的了解,但这些细节仍然存在
重复我在评论中提出的观点:在Java中,您从不将对象分配给变量;只能将引用指定给对象。或者,换句话说,您的变量都不是对象。具有超类型引用类型的变量可以包含对子类型实例的引用。将子类型实例指定给变量不会以任何方式更改实例;它只是拓宽了参考的类型。所有实例数据仍然存在,并且可以通过向下转换进行检索。就是
Student s = new Student("John", "Master's");
Person p = s; // no cast needed for a widening conversion
与以下内容完全相同:
Person p = new Student("John", "Master's");
Student s = (Student) p; // cast required for a narrowing conversion
编辑也许这有助于澄清问题。
假设有第二个子类Person
:
class Teacher extends Person
{
private String department;
}
现在您可以执行以下操作:
Person p = new Teacher("Fred", "Physics");
Teacher t = (Teacher) p;
但如果您以后尝试这样做:
p = new Teacher("Fred", "Physics");
Student s = (Student) p; // Error!
您将得到一个,因为在程序中的这一点上,p
现在是对一个对象的引用(Teacher
),该对象不是Student
这里有一个类比。在英语中,你可能会说,“我有一只宠物动物”。这与动物的类型无关。(例如,你无法知道宠物是否会吠叫。)另一方面,如果你说“我有一只宠物狗”,那么问它是否会对陌生人吠叫是有道理的。关键是:称你的宠物为动物并不能改变它是(或不是)狗的事实。使用更通用(例如,基类)的引用类型来存储对象引用不会改变对象本身的性质。您失去了对对象细节的了解,但这些细节仍然存在
重复我在评论中提出的观点:在Java中,您从不将对象分配给变量;只能将引用指定给对象。或者,换一种说法,您的变量都不是对象。变量不包含对象。变量包含标识对象的引用。如果有一个汽车识别号列表(美国的VIN),该列表本身可能包含许多不同种类的汽车的编号;从列表的角度来看,每个号码都可以识别一辆车,但一个号码可能会识别福特福克斯,另一个是丰田,另一个是雪佛兰敞篷车等等。如果在列表上写下雪佛兰敞篷车的号码,列表将不知道它是一辆敞篷车,因此无法说明“在列表中第五辆车上升起车顶”,但不首先确定第五个VIN标识的车具有活顶。车顶不会是在确定该车为活顶时出现的;车顶及其状态(升起或降下)无论谁知道它们,都将继续存在。变量不包含对象。变量包含标识对象的引用。如果有汽车识别号列表(美国的VIN),列表本身可能包含许多不同种类的汽车的编号;从列表的角度来看,每个编号都可以识别一辆汽车,但一个编号可以识别FordFocus,另一个编号可以识别ToyotaPrius,另一个编号可以识别ChevroletSebringConvertive,等等。如果将ChevroletSebringConvertive的编号写在列表上,则列表将显示不知道这是一辆敞篷车,因此如果不首先确定第五个VIN标识的汽车有一个敞篷车,就不能说“在列表中的第五辆汽车上升起车顶”。车顶不是在汽车被标识为敞篷车时出现的;车顶及其状态(升起或降下)无论谁知道它们,它们都会继续存在。所以即使