2

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

Fish f;
Tuna t = new Tuna();

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

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

金枪鱼“是”鱼是可以的。鱼“是”金枪鱼是不行的。因此 f=t 不应该是可以的,而 t=f 应该是可以的。但从我上面的例子来看,情况正好相反!

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

编辑. 非常感谢以下所有回复。从他们那里,我现在了解到:

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

4

3 回答 3

2

你很接近,但你在一个陈述中是错误的。

金枪鱼“是”鱼还可以

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

鱼“是”金枪鱼不好

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

. 因此 f=t 不应该是可以的,而 t=f 应该是可以的

我不同意,由于您上面的陈述,您刚刚说了相反的话。在上个问题中,您说每条鱼都是金枪鱼(t=f)而不是每条金枪鱼都是鱼(f=t)——这显然是错误的。

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

您必须记住,=这并不意味着相等(==在 java 中是相等的),为了更好地理解,请尝试从右到左阅读这些语句。

于 2013-10-24T06:41:16.653 回答
1

变量的值f是一个参考。这可以是空引用,也可以是对“是鱼”的任何对象的引用。由于Tuna对象是Fish对象,因此可以从 复制值t,该值必须是空引用或对Tuna对象的引用。

赋值只是将右侧表达式的值复制到左侧的变量中。这就是它所做的一切。

换句话说:你可以对 a 做的任何事情Fish,你都可以对 a 做任何事情Tuna。所以没有这样的价值t

f = t;
f.swim();

是荒谬的。(t当然可以是空引用,但这在类型系统中不被视为问题。)只要是非空的,总会有适当的方法可以调用。swimt

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

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

那么这就没有意义,因为你不能要求 aString游泳。

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

于 2013-10-24T06:33:34.750 回答
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();

   }
}
于 2013-10-24T07:40:52.477 回答