[英]Why are subclasses' private variables kept when stored in a superclass type variable?
I must have missed something basic in inheritance since it doesn't make sense to me. 我一定错过了继承中的一些基本知识,因为这对我来说没有意义。
Given these two classes: 给定这两个类:
class Person
{
private String name;
}
class Student extends Person
{
private String degree;
}
Why is it possible to create a new Student
object, store it in a Person
type variable and still be able to keep the variable String degree
and have access to it? 为什么可以创建一个新的
Student
对象,将其存储在Person
类型的变量中,并且仍然能够保留变量String degree
并可以访问它?
Person p = new Student("John", "Master's");
I thought that this is possible to use the above initialization because p
will not have any variable other than name
, since a Person
variable can't contain a degree
variable, and so it's legal - but when you do that, degree
doesn't exist in p
. 我认为可以使用上述初始化,因为
p
除了name
之外将没有任何变量,因为Person
变量不能包含degree
变量,所以这是合法的-但是当您这样做时, degree
不存在在p
。
That's what I thought the reason was behind the fact that the opposite is illegal 这就是我认为相反的事实是非法的事实的原因
( Student s = new Person("John");
) - because then s
will not have its other variable ( degree
) initialized. (
Student s = new Person("John");
)-因为s
不会初始化其其他变量( degree
)。
A variable with a type of reference to a supertype can hold a reference to an instance of a subtype. 具有对超类型的引用类型的变量可以保存对子类型的实例的引用。 Assigning the subtype instance to the variable does not change the instance in any way;
分配亚型实例变量以任何方式不改变的情况下; it just broadens the type of reference.
它只是扩大了参考的类型。 All the instance data is still there, and can be retrieved by a down-cast.
所有实例数据仍然存在,并且可以通过向下广播检索。 That is,
那是,
Student s = new Student("John", "Master's");
Person p = s; // no cast needed for a widening conversion
is exactly the same as: 与以下内容完全相同:
Person p = new Student("John", "Master's");
Student s = (Student) p; // cast required for a narrowing conversion
EDIT Perhaps this will help clarify things. 编辑也许这将有助于澄清事情。 Suppose there was a second subclass of
Person
: 假设存在
Person
的第二个子类:
class Teacher extends Person
{
private String department;
}
Now you can do this: 现在您可以执行以下操作:
Person p = new Teacher("Fred", "Physics");
Teacher t = (Teacher) p;
But if you later tried to do this: 但是,如果您以后尝试执行此操作:
p = new Teacher("Fred", "Physics");
Student s = (Student) p; // Error!
you'll get a ClassCastException
because at that point in the program, p
is now a reference to an object (an instance of Teacher
) that is not a Student
. 您将获得
ClassCastException
因为在程序中的那一点, p
现在是对不是Student
的对象( Teacher
的实例)的引用。
Here's an analogy. 这是一个比喻。 In English, you might say, "I have a pet animal".
用英语,您可能会说:“我有一只宠物”。 This says nothing about the type of animal.
这与动物的种类无关。 (You cannot know whether the pet barks, for instance.) On the other hand, if you say, "I have a pet dog", then it makes sense to ask whether it barks at strangers.
(例如,您不知道宠物是否吠叫。)另一方面,如果您说“我有一只宠物狗”,那么问它是否对陌生人吠叫是很有意义的。 The key point is: calling your pet an animal doesn't change the fact that it is (or is not) a dog .
关键是: 将宠物称为动物不会改变它是(或不是)狗的事实 。 Exactly the same thing is going on with Java references—using a more general (eg, base class) reference type to store the object reference does not change the nature of the object itself.
Java引用确实发生了同样的事情-使用更通用的(例如,基类)引用类型来存储对象引用不会改变对象本身的性质。 You lose knowledge of the details of the object, but those details are still there.
您会丢失对象详细信息的知识 ,但是这些细节仍然存在。
To repeat the point I made in my comment: you never assign objects to variables in Java; 重复我在评论中提出的观点:在Java中,永远不要将对象分配给变量; you only assign references to objects.
您只分配对对象的引用 。 Or, to put it another way, none of your variables are objects.
或者,换句话说,您的变量都不是对象。
Variables don't hold objects. 变量不持有对象。 Variables hold references , which identify objects.
变量包含引用 ,这些引用 标识对象。 If one has a list of automotive vehicle identification numbers (VIN in the US), the list itself may contain numbers for cars of many different sorts;
如果列出了汽车识别号(在美国为VIN),则列表本身可能包含许多不同类型的汽车的号。 from the perspective of the list, each number is known to identify a Vehicle, but one number might identify FordFocus, another a ToyotaPrius, another a ChevroletSebringConvertible, etc. If one writes the number of a ChevroletSebringConvertible on the list, the list would have no idea that it was a convertible, and so one couldn't say "Raise the top on the fifth car on the list" without first establishing that the car identified by the fifth VIN had a convertible top.
从列表的角度来看,已知每个数字都可以标识车辆,但是一个数字可以标识FordFocus,另一个可以标识ToyotaPrius,另一个可以标识ChevroletSebringConvertible,等等。如果在该列表上写了一个ChevroletSebringConvertible的数字,则该列表将没有认为这是敞篷车,因此如果不先确定第五个VIN所标识的汽车具有敞篷车顶,就不能说“提高列表中第五辆车的顶部”。 The top wouldn't be something that came into existence when the car was identified as a convertible;
当汽车被确认为敞篷车时,顶部就不会存在。 the top and its state (raised or lowered) would continue to exist regardless of who knew about them.
无论谁知道它们,顶部及其状态(升高或降低)都将继续存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.