2013-10-24 2 views
2

Скажем, у меня есть суперкласс «Рыба» и подкласс «Туна». Я не понимаю, почему это работает:Смутно об обход иерархии классов с полиморфизмом

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 относится к объекту тунца , и поэтому является совместимым типом для использования f. Это совместимо, потому что тунцом является рыба.

ответ

1

Значение переменной f является ссылкой. Это может быть нулевая ссылка или ссылка на любой объект, который является «рыбой». Поскольку объект Tuna является объектом Fish, вполне возможно скопировать значение от t, которое должно быть либо нулевой ссылкой, либо ссылкой на объект Tuna.

Назначение только копирует значение выражения в правой части переменной в левой части. Это все, что он делает.

Другими словами: все, что вы можете сделать для Fish, можно сделать с помощью Tuna. Таким образом, нет никакого значения t, что:

f = t; 
f.swim(); 

бессмысленна. (t может быть нулевой ссылкой, конечно, но это не рассматривается как проблема в системе типов как таковая.) всегда быть подходящим методом swim для вызова, если t не имеет значения.

Сравните это с другим типом. Если бы мы имели:

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

затем что не имеет смысла, потому что вы не можете попросить String плавать.

Правила безопасности типа гарантируют, что вы никогда не сможете попытаться вызвать метод (или получить доступ к полю) и обнаружить, что используете тип, для которого этот метод/поле просто не существует. Тот факт, что Tuna распространяется на Fish, означает, что все, что вы можете сделать с «общей» рыбой, вы также можете сделать с тунцом.

+1

Строки не умеют плавать? О, МОЙ БОГ! Я был просвещен! –

+0

Спасибо! Я отредактировал свой O.P., чтобы отразить то, что я узнал. – user2911290

2

Вы близки, но вы ошибаетесь только в одном заявлении.

Tuna "является" Рыба OK

Я согласен - это означает утверждение е = т (рыба = тунец), чтобы быть правильным.

Рыба «является» Тунец не в порядке

Я согласен - это означает, что утверждение т = п (тунец = рыба), чтобы быть неправильным.

. Поэтому f = t не должно быть ОК, и t = f должно быть ОК

Я не согласен, из-за ваших статуэток над вами просто что-то сказал. В последнем Qoute вы сказали, что каждая рыба является тунцом (t = f), и не каждый тунец является рыбой (f = t) - это, очевидно, неправильно.

Если тунцом является рыба, то F = T, потому что любой тунцом будет рыба. Но мы не можем сказать, что каждая рыба - это тунец, можем ли мы?

Вы должны помнить, что = не означает равенства (whitch == делает в java), и для лучшего понимания попробуйте прочитать эти statemets справа налево.

+1

+1 для предложения читать справа налево. –

+1

Спасибо, да, я согласен, что чтение «действия копирования задания» справа налево помогает прояснить ситуацию. – user2911290

1

У вас есть класс рыбы Super, который имеет метод плавания, а тунца - подкласс рыбы. So Тунец - это рыба: ее хорошо Но рыба - это тунца: это не нормально. То же самое Вы можете назначить рефлекс тунца для рыбы, но рыбий ref не может к тунцу. So

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

    } 
} 
+0

К сожалению, код «Случай B, правильный» не работает. – user2911290

Смежные вопросы