问题描述
:作为一般规则,如果类定义了子类可以访问的字段,则子类 不应 重新定义该字段。这真是个坏主意。首先,您所看到的是使
字段正常工作。重新定义子类中的非私有字段要求受到伤害。(当然,如果Joe编写Mammal
而Mary编写Zebra
并且Joe在某个时候添加了一个字段,Mammal
而该字段恰好与Mary所使用的字段冲突Zebra
,则Mary对此无能为力。这是将所有字段设为私有的原因之一。)
但是,即使在隐藏的情况下,为什么子类对象也存储超类变量的值。
这里的关键是要记住,字段不是多态的,只是方法。因此,对象中 必须 有两个name
字段(一个来自from Mammal
,一个来自fromZebra
),因为使用A Mammal
型引用的代码需要查看Mammal
name
,而使用Zebra
A型引用的代码需要查看Zebra
name
。
这就是为什么您的代码显示“ Furry bray”,然后显示“ stripes bray”的原因。你可以通过获得“毛茸茸的叫声”m
,因为访问name
的m
(一个Mammal
-typed变量)访问Mammal
的name
(不是多态),让您‘毛茸茸’。但是随后您makeNoise
使用m
并返回"bray"
了方法,因为调用的方法是onZebra
(多态的)方法。然后,您再次使用z
(Zebra
类型参考)进行操作,并看到“ stripes
bray”,因为z
访问Zebra
的是name
,而不是Mammal
。
您可能遇到的下一个问题是:如果我们将makeNoise
两个类都更改为:
String makeNoise() {
return this.name;
}
为什么要ZooKeeper
编码
Mammal m = new Zebra();
System.out.println(m.name + m.makeNoise());
Zebra z = new Zebra();
System.out.println(z.name + z.makeNoise());
从给我们“毛茸茸条纹” m
和stripes stripes
从z
?
这是相同的原因,只是它的表示形式不同。从类型引用m.name
访问,因此看到的(不是多态的)。调用
方法(多态),以及里面的,有型,即使我们把它称为从-typed
(等用途的)。在那里使用Zebra的事实以及在代码中键入内容的事实都是Java多态性的关键。name``Mammal``Mammal``name``m.makeNoise
makeNoise``Zebra``makeNoise``this``Zebra``Mammal``m``this.name``Zebra``name``makeNoise``this``Zebra``Zebra
让我们更进一步:如果Zebra
根本没有定义makeNoise
怎么办?
class Mammal {
String name = "furry ";
String makeNoise() {
return this.name;
}
}
class Zebra extends Mammal {
String name = "stripes ";
}
现在,我们从中获得“毛茸茸” m
和“条纹毛茸”z
。其原因与上述相同:引用的类型确定使用哪个字段,并且在Mammal
代码(makeNoise
)中this
具有类型Mammal
。因此,即使我们调用makeNoise
usingz
,由于Zebra
没有makeNoise
,也Mammal
被称为,所以查找的引用name
具有类型Mammal
。
有什么用吗?
这是
正常工作,特别是在私人领域的情况下类。Mammal
代码不必担心子类会出现并重新定义其字段。您可能有一个10级深的类层次结构,每个类都定义了自己的name
,这很好,每个级别的代码都可以使用name
它定义的。
解决方法
在以下代码中-
class Mammal {
String name = "furry ";
String makeNoise() {
return "generic noise";
}
}
class Zebra extends Mammal {
String name = "stripes ";
String makeNoise() {
return "bray";
}
}
public class ZooKeeper {
public static void main(String[] args) {
new ZooKeeper().go();
}
void go() {
Mammal m = new Zebra();
System.out.println(m.name + m.makeNoise());
Zebra z = new Zebra();
System.out.println(z.name + z.makeNoise());
}
}
如果在eclipse的调试窗口中看到,则两个对象(m
和z
)都包含name
变量(furry
和stripes
)的两个值。
我确实知道在多态中,子类也可以使用超类的泛型方法。但是,即使在隐藏的情况下,为什么子类对象也存储超类变量的值。有什么用吗?