关于Java向上/向下转换和继承优先级的问题
在这些情况下,很难理解上行/下行以及静态绑定和动态绑定的复杂性。请考虑以下类和接口示例:关于Java向上/向下转换和继承优先级的问题,java,class,inheritance,binding,casting,Java,Class,Inheritance,Binding,Casting,在这些情况下,很难理解上行/下行以及静态绑定和动态绑定的复杂性。请考虑以下类和接口示例: public class Marsupial { private String name; Marsupial(String name) { this.name = name; } void eats() { System.out.println("Eats #1");
public class Marsupial { private String name;
Marsupial(String name) {
this.name = name;
}
void eats() {
System.out.println("Eats #1");
}
String getName(){ return name;
}
}
abstract class Herbivore extends Marsupial {
Herbivore(String name) {
super(name);
}
void eats() {
System.out.println("Eats #2");
}
abstract void chews(boolean b);
}
interface Australian {
public void greets(Koala k);
}
public class Koala extends Herbivore implements Australian {
Koala(String name) {
super(name);
}
public void greets(Koala k) {
System.out.println("G'day mate!");
System.out.println(getName() + " " + k.getName() );
}
void chews(boolean b) {
System.out.println("Yum yum!");
}
void chews(int i) { System.out.println("Delicious!");
}
void likes(Koala k) {
greets(k);
k.greets(this); }
}
现在,当我创建一个driver类来使用所有的类时,我注意到一些奇怪的事情发生了,我不知道为什么
比如说,
public class Driver {
public static void main(String[] args) {
Marsupial m = new Marsupial("Kate");
Marsupial m2 = new Koala("Kim");
System.out.println(m.getClass() == m2.getClass());
}
}
事实证明这是错误的。他们不是同一类人。那么这里到底发生了什么。左边是有袋动物,右边是其他动物。那么,当我们调用方法时,正确的是唯一重要的事情吗?当编译器运行并查看方法时,检查equals运算符的右侧,并说ok这是某某类,因此在确定要使用的类时,请使用在右侧定义的类的方法
而且
如果在我写的主方法中:
Marsupial m = new Koala("jack");
m.eats();
这张打印出来的是2。这是因为无尾熊没有eats方法,只是返回到链的上一级,所以下一级将是Herbivor,因为它有一个eats()方法,这就是被调用的方法,这是想法吗
主方法中的另一个示例:
Herbivore h = new Koala("June");
((Marsupial)h).eats();
这里让我感到不舒服的是,我们可以使用抽象类作为对实际对象的引用,就像这里Herbivor是一个抽象类,因此不能实例化,但可以将它分配给实例化对象的类。
但最让我困惑的是,现在我们在考拉类中,我们调用eats()方法,但随后我们将变量向上转换为有袋动物。因此,这会自动将我们放入有袋动物类,因此无论何时我们调用一个方法,即使它在其他类中,有袋动物类方法也是被调用的方法,因为我们将它键入有袋动物,因此它吃#1
另一个令人困惑的方面是,如果我们主要这样做:
Australian a = new Koala("Khloe");
a.chews(true);
我们看到一个接口被分配给一个子类实例化。这让我很困惑,用a.chews来称呼什么(真的)。既然它被定义为考拉对象,那么我们就在考拉类中,必须使用考拉方法(如果它们存在的话),如果没有的话,我们就上一层去检查它们是否有这个方法等等。但是这里的方法是无效的。那么,只有在澳大利亚有一个原型方法并且考拉定义了它的情况下,它才有效吗?那就行了?这就是将接口设置为其子类对象背后的想法吗?尽管无尾熊有这种方法,因为澳大利亚人没有,但它不会起作用
如果我们主要有代码,比如:
Herbivore h = new Koala("Stacy");
h.chews(true);
这将打印出“Yum-Yum”,只是因为Herbivore有一个未定义的原型方法,而考拉定义了它。但是,如果《食草动物》没有这种原型,这种方法是行不通的
我的最后一个问题是,如果这是在主系统中运行的:
Herbivore h = new Koala("Kali");
h.chews(4);
这是行不通的,因为尽管考拉在那里有这个方法,但它并没有在《食草动物》中定义,所以它是无效的
请帮忙,你能提供的任何更正或信息都会很有帮助
谢谢所有问题的答案只有一个:尽可能 JVM担心它不会 关心一下这个变量 类型,但仅限于实际类型( 一个与
new
关键字一起使用)
. 变量类型用于
编译器仅用于确保类型
安全早在发展中
可能。我记不清这里有多少问题;但它们都是有价值的,你们为什么不试试看,看看它们的多样性呢。这比编写这个问题花费的时间要少。关于这一点的传统观点是,变量具有声明的类型,对象具有运行时类型。声明的类型告诉您允许对实例调用哪些方法。如果子类型具有该方法,但声明的类型没有,则不能调用它。运行时类型确定实例方法的实际执行版本。如果存在,则运行时类型中的覆盖将获胜。