在 Java 中向上转换子类引用
Upcasting a subclass reference in Java
我正在 Thinking in Java 第 4 版 中做以下练习,作者 Bruce Eckel:
Exercise 16: (2) Create a class called Amphibian. From this, inherit a class called Frog. Put appropriate methods in the base class. In main(), create a Frog and upcast it to Amphibian and demonstrate that all the methods still work.
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();
}
}
在这个简单的程序中,其实并没有什么区别。但是如果你有一个 Amphibian f
,它可以指代任何两栖动物,而不仅仅是 Frog
。您仍然使用 Amphibian
提供的所有方法,即使它是 Frog
的实例
有关多态性的描述,请参阅 What is polymorphism, what is it for, and how is it used?。
这就是我们所说的多态性。那是许多形状。同一物体的多种形状。正如您所了解的,同一对象可以称为青蛙,也可以称为两栖动物。当 referral 为 Amphibian 时,原始对象仍然是 Frog,因此调用重写方法。
But I don't understand What is the difference between Frog f = new Frog(); and Amphibian 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()
时,您正在为实现编程。
现在开始讨论本书要求您尝试的实际问题:
In main( ), create a Frog and upcast it to Amphibian and demonstrate
that all the methods still work.
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有什么用但是既然标题已经被别人编辑过了,为什么不一并回答呢?向上转型在某些情况下很有用,例如显式调用重载方法的特殊形式。有关更多详细信息,请参阅 this 答案。
太明显的区别,你可以添加一个方法 jump() 到青蛙(但不是基础 class 两栖动物:
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();
这种编码方式非常流行,被称为编码到基础Class或接口
What is the difference between Frog f = new Frog();
and Amphibian f = new Frog();
从你的例子我们可以看出Frog
继承了Amphibian
。因此,任何声明为 Amphibian
类型的变量都可以始终将具有超级 class 的对象实例存储为 Amphibian
在您的情况下 Frog
。至于示例代码,它没有区别。
但是在您的示例中找不到两者之间的细微差别。考虑以下因素:
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
class 中没有方法 croak
。所以会抛出一个错误。但是如果你像这样存储它:
Frog f = new Frog();
f.croak(); //This will work.
这是有效的,因为 JVM 将 f 视为类型 Frog
并且 class Frog
具有方法 croak
.
当然,您可以通过将 f 类型转换为 Frog
作为 :
Amphibian f = new Frog();
((Frog)f).croak(); //This will work.
我正在 Thinking in Java 第 4 版 中做以下练习,作者 Bruce Eckel:
Exercise 16: (2) Create a class called Amphibian. From this, inherit a class called Frog. Put appropriate methods in the base class. In main(), create a Frog and upcast it to Amphibian and demonstrate that all the methods still work.
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();
}
}
在这个简单的程序中,其实并没有什么区别。但是如果你有一个 Amphibian f
,它可以指代任何两栖动物,而不仅仅是 Frog
。您仍然使用 Amphibian
提供的所有方法,即使它是 Frog
的实例
有关多态性的描述,请参阅 What is polymorphism, what is it for, and how is it used?。
这就是我们所说的多态性。那是许多形状。同一物体的多种形状。正如您所了解的,同一对象可以称为青蛙,也可以称为两栖动物。当 referral 为 Amphibian 时,原始对象仍然是 Frog,因此调用重写方法。
But I don't understand What is the difference between Frog f = new Frog(); and Amphibian 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()
时,您正在为实现编程。
现在开始讨论本书要求您尝试的实际问题:
In main( ), create a Frog and upcast it to Amphibian and demonstrate that all the methods still work.
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有什么用但是既然标题已经被别人编辑过了,为什么不一并回答呢?向上转型在某些情况下很有用,例如显式调用重载方法的特殊形式。有关更多详细信息,请参阅 this 答案。
太明显的区别,你可以添加一个方法 jump() 到青蛙(但不是基础 class 两栖动物:
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();
这种编码方式非常流行,被称为编码到基础Class或接口
What is the difference between
Frog f = new Frog();
andAmphibian f = new Frog();
从你的例子我们可以看出Frog
继承了Amphibian
。因此,任何声明为 Amphibian
类型的变量都可以始终将具有超级 class 的对象实例存储为 Amphibian
在您的情况下 Frog
。至于示例代码,它没有区别。
但是在您的示例中找不到两者之间的细微差别。考虑以下因素:
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
class 中没有方法 croak
。所以会抛出一个错误。但是如果你像这样存储它:
Frog f = new Frog();
f.croak(); //This will work.
这是有效的,因为 JVM 将 f 视为类型 Frog
并且 class Frog
具有方法 croak
.
当然,您可以通过将 f 类型转换为 Frog
作为 :
Amphibian f = new Frog();
((Frog)f).croak(); //This will work.