关于遍历具有多态性的类层次结构感到困惑

时间:2013-10-24 06:31:48

标签: java polymorphism

假设我有一个名为Fish的超类,以及一个名为Tuna的子类。我不明白为什么会这样:

Fish f;
Tuna t = new Tuna();

f=t;  // I am confused about this statement
f.swim();  // (Tuna's swim method is invoked)

为什么鱼变量允许“参与”(因为缺少更好的短语)更专业的金枪鱼对象?我明显错误的“noob OOP Java大脑”的工作方式是:

金枪鱼“是一种”鱼是可以的。鱼“是一个”金枪鱼不行。因此f = t不应该没问题,t = f应该没问题。但从我上面的例子来看,情况恰恰相反!

非常感谢您对此的任何帮助。我提前为我的无知道歉,因为我刚刚开始学习Java。

修改即可。非常感谢下面的所有回复。从他们,我现在明白:

名为f的变量是Fish类型,因此,允许包含位于变量t内的数据值(对象引用),因为t指的是Tuna对象,因此它是兼容的类型f使用。这是兼容的,因为金枪鱼是一种鱼。

3 个答案:

答案 0 :(得分:2)

你很亲密,但只有一个陈述你错了。

  

金枪鱼“是”鱼还可以

我同意 - 这意味着声明f = t(fish = tuna)是正确的。

  

鱼“是”金枪鱼不行

我同意 - 这意味着声明t = f(tuna = fish)是不正确的。

  

。因此f = t应该不行,t = f应该没问题

我不同意,由于你上面的陈述,你刚才说了一些相反的话。 在最后一次,你说每条鱼都是金枪鱼(t = f)而不是每条金枪鱼都是鱼(f = t) - 这显然是错误的。

如果金枪鱼是鱼,那么F = T因为任何金枪鱼都是鱼。但我们不能说每条鱼都是金枪鱼吗?

你必须记住,=并不意味着平等(whitch ==在java中),为了更好地理解,请尝试从右到左阅读这些状态。

答案 1 :(得分:1)

f变量的值是引用。这可以是空引用,也可以是对“是鱼”的任何对象的引用。由于Tuna对象是Fish对象,因此可以复制t中的值,该值必须是空引用或对Tuna对象的引用。< / p>

分配只是将右侧表达式的值复制到左侧的变量。就是这样。

换句话说:您可以对Fish执行任何操作,您可以执行Tuna。所以t没有价值:

f = t;
f.swim();

是荒谬的。 (t当然可以是空引用,但这并不是类型系统中的问题。)总是是一个适当的swim方法来调用,只要t非空。

将其与不同类型进行比较。如果我们有:

String s = "foo";
f = s;
f.swim();

然后 没有意义,因为你不能要求String游泳。

类型安全规则确保您永远不会尝试调用方法(或访问字段)并发现您正在使用的方法/字段根本不存在。 Tuna延伸Fish的事实意味着您可以使用“普通”鱼做任何事情,也可以使用金枪鱼。

答案 2 :(得分:1)

你有Fish Super Class游泳方法,Tuna是Fish的子类。 所以 金枪鱼是鱼:好的 但鱼是金枪鱼:不行。 相同 您可以将金枪鱼参考分配给鱼参考,但鱼参考不能参加金枪鱼。 所以

public class Fish {
    public void swim(){
         System.out.print("Hello Fish");
    }
}

public class Tuna extends Fish{
    public void swim(){
        System.out.print("Hello Tuna");
    }


    public static void main(String[] ar){
       //Case A 
       Fish f=new Fish();
       Tuna t;
       t=(Tuna) f;//wrong - it will not cast to tuna object
       t.swim();
      //Case B  //correct
       Fish f;
       Tuna t=new Tuna();
       t=f 
       t.swim();

   }
}