Say I have a superclass called Fish, and a subclass called Tuna. I don't understand why this works:
Tuna t = new Tuna();
f=t; // I am confused about this statement
f.swim(); // (Tuna's swim method is invoked)
The value of the
f variable is a reference. That can be a null reference, or a reference to any object which "is a fish". As a
Tuna object is a
Fish object, it's fine to copy the value from
t, which must either be a null reference or a reference to a
Assignment just copied the value of the expression on the right hand side to the variable on the left hand side. That's all it does.
To put it another way: anything you can do to a
Fish, you can do to a
Tuna. So there's no value of
t such that:
f = t; f.swim();
is nonsensical. (
t could be a null reference of course, but that's not seen as a problem in the type system as such.) There will always be an appropriate
swim method to call, so long as
t is non-null.
Compare that with a different type. If we had:
String s = "foo"; f = s; f.swim();
then that wouldn't make sense, because you can't ask a
String to swim.
The type safety rules ensure that you can never try to call a method (or access a field) and find that you're using a type for which that method/field simply doesn't exist. The fact that
Fish means that anything you can do with a "general" fish, you can do with a tuna too.