简体   繁体   English

上载Java中的子类引用

[英]Upcasting a subclass reference in Java

I'm doing the following exercise in Thinking in Java 4th Edition by Bruce Eckel: 我在Bruce Eckel撰写的《 Java思维第四版 》中进行以下练习:

Exercise 16: (2) Create a class called Amphibian. 练习16:(2)创建一个名为Amphibian的类。 From this, inherit a class called Frog. 从此继承一个名为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. 在main()中,创建Frog并将其向上转换为两栖动物,并演示所有方法仍然有效。

What is the difference between Frog f = new Frog(); Frog f = new Frog();什么区别Frog f = new Frog(); and Amphibian f = new Frog(); Amphibian f = new Frog(); in: 在:

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();
    }
}

But I don't understand What is the difference between Frog f = new Frog(); 但是我不明白Frog f = new Frog();和Frog有什么区别? and Amphibian f = new Frog(); 和两栖动物f = new Frog();

To understand the difference, let's add another method in Frog that is not in Amphibian 要了解它们之间的区别,让我们在Frog中添加另一种不在Amphibian

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
    void come() { System.out.println("come"); }
}

Now let's take a look at what's the difference : 现在让我们看一下有什么区别:

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
    }
}

Bottom line. 底线。 Frog is an Amphibian so Frog can do whatever an Amphibian can. FrogAmphibian所以Frog可以做Amphibian可以做的任何事情。 Amphibian is not a Frog so Amphibian can't do everything a Frog can. Amphibian不是Frog所以Amphibian不能做Frog能做的一切。

When you say Amphibian a = new Frog() , you are programming to an interface (not the java interface but the general meaning of interface). 当您说Amphibian a = new Frog() ,您是在编程接口(不是java接口,而是接口的一般含义)。 When you say Frog f = new Frog() you are programming to an implementation. 当您说Frog f = new Frog()您正在编程实现。

Now coming to the actual question that the book asks you to try : 现在来看书要求您尝试的实际问题:

In main( ), create a Frog and upcast it to Amphibian and demonstrate that all the methods still work. 在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                
        }
    }

I don't think you meant to ask What's the use of upcasting but since the title has already been edited by someone else, why not answer that as well? 我不认为您要问的是upcasting的用途,但由于标题已经由其他人编辑,为什么不回答呢? Upcasting is useful in certain situations such as calling specialized forms of an overloaded methods explicitly. 上载在某些情况下很有用,例如明确调用重载方法的特殊形式。 See this answer for additional details. 有关其他详细信息,请参见此答案。

In this simple program, there is actually no difference. 在这个简单的程序中,实际上没有区别。 But if you have a Amphibian f , it can refer to any amphibian, not just a Frog . 但是,如果您有Amphibian f ,它可以指代任何两栖动物,而不仅仅是Frog You still use all methods that an Amphibian provides, even if it is an instance of a Frog See What is polymorphism, what is it for, and how is it used? 您仍然使用Amphibian提供的所有方法,即使它是Frog的实例也是如此。请参阅什么是多态性,其用途以及如何使用? for a description of polymorphism. 用于描述多态性。

What is the difference between Frog f = new Frog(); Frog f = new Frog();什么区别Frog f = new Frog(); and Amphibian f = new Frog(); Amphibian f = new Frog();

From your example we can see that Frog inherits Amphibian . 从您的示例中我们可以看到Frog继承了Amphibian So any variable that is declared of type Amphibian can always store instance of objects which have super class as Amphibian in your case Frog . 因此,任何声明为Amphibian类型的变量都可以始终在您的案例Frog存储具有超类为Amphibian的对象的实例。 As for the example code it has no difference. 至于示例代码,没有区别。

But there is a subtle difference between the two that can not be found in your example. 但是,在您的示例中找不到两者之间的细微差别。 Consider the following: 考虑以下:

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
    void croak(){ System.out.println("croak");} //Added this extra line
}

Now if you store your Frog instance as 现在,如果您将Frog实例存储为

Amphibian f = new Frog();
f.croak(); //This will not work.

This is not working as because the JVM considers f as type Amphibian and in Amphibian class there is no method croak . 这是行不通的,因为JVM将f视为Amphibian类型,并且在Amphibian类中没有croak方法。 So an error is thrown. 因此会引发错误。 But if you store it like: 但是,如果您将其存储为:

Frog f = new Frog();
f.croak(); //This will work.

This is working because the JVM considers f as type Frog and the class Frog has the method croak . 这是工作,因为JVM认为˚F类型Frog和类Frog具有方法croak

Of course you can make the previous case work by type casting the f to Frog as : 当然,您可以通过将f强制转换为Frog来使前面的案例工作:

Amphibian f = new Frog();
((Frog)f).croak(); //This will work.

This is what we know as polymorphism. 这就是我们所说的多态性。 That is many shapes. 那是很多形状。 Many shapes of the same object. 同一对象的许多形状。 The same object can be referred to as Frog and it can be referred to as Amphibian, as you have learned. 如您所知,同一对象可以称为Frog,也可以称为两栖动物。 When referral is as Amphibian, still the original object is Frog so the overridden method is called. 当引用是两栖动物时,原始对象仍然是Frog,因此将调用覆盖的方法。

Too see the difference, you could add a method jump() to Frog (but not the to the base class Amphibian: 要了解两者之间的区别,您可以将方法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!
    }
}

This one is Simple If you use like below 这是简单的如果您使用如下

Frog f = new Frog();

Then you can't cast it to any other type. 这样就无法将其转换为其他任何类型。 However you can call all the Frog methods. 但是,您可以调用所有Frog方法。

But If you use like below 但是如果你像下面这样使用

Amphibian f = new Frog();

you can still change the object to some other amphibians without changing its reference by simply doing like this. 您仍然可以通过简单的操作将对象更改为其他两栖动物,而无需更改其引用。

f = new SomeOtherAmphibian();

This way of coding is very popular and known as coding to the Base Class or Interface 这种编码方式非常流行,被称为对基类或接口进行编码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM