在以下代码中-
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
)的两个值。
我确实知道在多态中,子类也可以使用超类的泛型方法。但是,即使在隐藏的情况下,为什么子类对象也存储超类变量的值。有什么用吗?
首先 :作为一般规则,如果类定义了子类可以访问的字段,则子类 不应 重新定义该字段。这真是个坏主意。首先,您所看到的是使 私有
字段正常工作。重新定义子类中的非私有字段要求受到伤害。(当然,如果Joe编写Mammal
而Mary编写Zebra
并且Joe在某个时候添加了一个字段,Mammal
而该字段恰好与Mary所使用的字段冲突Zebra
,则Mary对此无能为力。这是将所有字段设为私有的原因之一。)
但是,即使在隐藏的情况下,为什么子类对象也存储超类变量的值。
这里的关键是要记住,字段不是多态的,只是方法。因此,对象中 必须 有两个name
字段(一个来自from Mammal
,一个来自from
Zebra
),因为使用A Mammal
型引用的代码需要查看Mammal
name
,而使用Zebra
A型引用的代码需要查看Zebra
name
。
这就是为什么您的代码显示“ Furry bray”,然后显示“ stripes bray”的原因。你可以通过获得“毛茸茸的叫声”
m
,因为访问name
的m
(一个Mammal
-typed变量)访问Mammal
的name
(不是多态),让您‘毛茸茸’。但是随后您makeNoise
使用m
并返回"bray"
了方法,因为调用的方法是on
Zebra
(多态的)方法。然后,您再次使用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
Zebra
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
using
z
,由于Zebra
没有makeNoise
,也Mammal
被称为,所以查找的引用name
具有类型Mammal
。
有什么用吗?
这是 至关重要的
正常工作,特别是在私人领域的情况下类。Mammal
代码不必担心子类会出现并重新定义其字段。您可能有一个10级深的类层次结构,每个类都定义了自己的name
,这很好,每个级别的代码都可以使用name
它定义的。
我在Java中读到了关于将超类变量类型化为子类的知识,反之亦然。请告诉我哪些是有效的? 动物是超级类,有猫和狗子类。
我理解超类/子类之间的关系以及强制转换是如何工作的。但是,我的问题是,如果知道中间有一个类,你能把一个超类转换成一个特定的子类吗?例如,如果我有一个动物类对象包含一个BigDog对象,我可以将该对象强制转换为Dog吗?如果BigDog中有Dog中不存在的方法怎么办? 简而言之,你当然可以说超类对象是子类对象,但为什么你可以反转呢? 转念一想, Java在调用方法时检查的是:引用(DOG)是否有引用
在我的应用程序中,我有一个单一的活动架构,我为每个片段定义了一个“视图”类。 这个“视图”类包含视图状态和视图操作,它们引用视图的数据和操作。 例如,我有一个“MainFragment.kt”和一个相关的“MainView.kt”文件,它是这样的: 然后导入“主状态”和“操作”,并在“主状态ragment.kt”及其“视图模型”类中使用。 正如您所见,“MainView”被定义为一个对象,因为我不
问题内容: 请参阅下面的代码,其中的方法被覆盖,但变量没有被覆盖。为什么允许在子类中声明重复的变量? 问题答案: 为什么在子类方法中不覆盖超类的实例变量,请参见下面的代码… 因为实例变量不能在Java中覆盖。在Java中,只能重写方法。 当你声明一个与超类中现有字段同名的字段时,新字段将隐藏现有字段。超类中的现有字段仍存在于子类中,甚至可以使用…遵守常规的Java访问规则。 因为实例变量在Java
问题内容: 代码: 问题: 为什么Java允许执行以上代码,而C ++不允许执行? 上面的代码是否创建了无数个对象?由于本身包含一个对象,而该对象又包含一个本身具有对象的对象,依此类推。 问题答案: 两种语言之间关于您的问题的主要区别是Java是具有引用语义的语言(原始类型除外),而C ++是具有值语义的语言,该值允许通过引用和指针进行引用语义。 在两种语言中看起来 相似的 语法具有完全不同的含义
问题内容: 我有一些这样的代码。 超级班 子类 所以问题是我可以将超类的对象转换为子类吗?这个问题对我来说是正确的吗? 但它给Class Cast异常。 问题答案: 您可以将子类转换为超级类,反之亦然。如果“车辆”是“超级类”,而“汽车”是子类,则所有“汽车”(子代)都是“汽车”(“超级”),但并非所有“车辆”都是“汽车”。