[英]Upcasting a subclass reference in Java
我在Bruce Eckel撰写的《 Java思维第四版 》中进行以下练习:
练习16:(2)创建一个名为Amphibian的类。 从此继承一个名为Frog的类。 在基类中放置适当的方法。 在main()中,创建Frog并将其向上转换为两栖动物,并演示所有方法仍然有效。
Frog f = new Frog();
什么区别Frog f = new Frog();
和Amphibian f = new Frog();
在:
class Amphibian {
void go() { System.out.println("go"); }
void stop() { System.out.println("stop!"); }
}
class Frog extends Amphibian {
void go() { System.out.println("not go"); }
}
public class EFrog {
public static void main(String[] args) {
Frog f = new Frog();
f.go();
}
}
但是我不明白Frog f = new Frog();和Frog有什么区别? 和两栖动物f = new Frog();
要了解它们之间的区别,让我们在Frog
中添加另一种不在Amphibian
class Frog extends Amphibian {
void go() { System.out.println("not go"); }
void come() { System.out.println("come"); }
}
现在让我们看一下有什么区别:
public class EFrog {
public static void main(String[] args) {
Frog f = new Frog();
f.go();
f.come();
Amphibian a = f;
a.come();//this won't compile
}
}
底线。 Frog
是Amphibian
所以Frog
可以做Amphibian
可以做的任何事情。 Amphibian
不是Frog
所以Amphibian
不能做Frog
能做的一切。
当您说Amphibian a = new Frog()
,您是在编程接口(不是java接口,而是接口的一般含义)。 当您说Frog f = new Frog()
您正在编程实现。
现在来看书要求您尝试的实际问题:
在main()中,创建一个Frog并将其向上转换为两栖动物,并演示所有方法仍然有效。
public class EFrog {
public static void main(String[] args) {
Frog f = new Frog();
Amphibian g = (Amphibian)f;//this is an upcast
g.go(); //okay since Amphibian can go
g.come();//not okay since Amphibian can't come
}
}
我不认为您要问的是upcasting的用途,但由于标题已经由其他人编辑,为什么不回答呢? 上载在某些情况下很有用,例如明确调用重载方法的特殊形式。 有关其他详细信息,请参见此答案。
在这个简单的程序中,实际上没有区别。 但是,如果您有Amphibian f
,它可以指代任何两栖动物,而不仅仅是Frog
。 您仍然使用Amphibian
提供的所有方法,即使它是Frog
的实例也是如此。请参阅什么是多态性,其用途以及如何使用? 用于描述多态性。
Frog f = new Frog();
什么区别Frog f = new Frog();
和Amphibian f = new Frog();
从您的示例中我们可以看到Frog
继承了Amphibian
。 因此,任何声明为Amphibian
类型的变量都可以始终在您的案例Frog
存储具有超类为Amphibian
的对象的实例。 至于示例代码,没有区别。
但是,在您的示例中找不到两者之间的细微差别。 考虑以下:
class Frog extends Amphibian {
void go() { System.out.println("not go"); }
void croak(){ System.out.println("croak");} //Added this extra line
}
现在,如果您将Frog
实例存储为
Amphibian f = new Frog();
f.croak(); //This will not work.
这是行不通的,因为JVM将f视为Amphibian
类型,并且在Amphibian
类中没有croak
方法。 因此会引发错误。 但是,如果您将其存储为:
Frog f = new Frog();
f.croak(); //This will work.
这是工作,因为JVM认为˚F类型Frog
和类Frog
具有方法croak
。
当然,您可以通过将f强制转换为Frog
来使前面的案例工作:
Amphibian f = new Frog();
((Frog)f).croak(); //This will work.
这就是我们所说的多态性。 那是很多形状。 同一对象的许多形状。 如您所知,同一对象可以称为Frog,也可以称为两栖动物。 当引用是两栖动物时,原始对象仍然是Frog,因此将调用覆盖的方法。
要了解两者之间的区别,您可以将方法jump()添加到Frog(但不能将其添加到基类Amphibian:
class Amphibian {
void go() { System.out.println("go"); }
void stop() { System.out.println("stop!"); }
}
class Frog extends Amphibian {
void go() { System.out.println("not go"); }
void jump() { System.out.println("jump!"); }
}
public class EFrog {
public static void main(String[] args) {
Frog f = new Frog();
f.go();
f.jump(); // works
Amphibian a = new Frog();
a.jump(); // will not compile!
}
}
这是简单的如果您使用如下
Frog f = new Frog();
这样就无法将其转换为其他任何类型。 但是,您可以调用所有Frog
方法。
但是如果你像下面这样使用
Amphibian f = new Frog();
您仍然可以通过简单的操作将对象更改为其他两栖动物,而无需更改其引用。
f = new SomeOtherAmphibian();
这种编码方式非常流行,被称为对基类或接口进行编码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.