繁体   English   中英

上载Java中的子类引用

[英]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
    }
}

底线。 FrogAmphibian所以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.

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