You could reassign one
to an object of some other subclass of car
:
one = new Ford(...);
But you can't reassign two
like that, since it's restricted to being an opel
.
If m
is a method that's defined in the opel
class but not the car
class, then the compiler will give you an error if you do this:
one.m();
But this is OK:
two.m();
since it knows two
is restricted to being an opel
, so it knows that method m
will exist.
Generally, you want to declare your variables to be the broadest type possible. That is, if you're only going to use methods in car
, then declare it with type car
(like you did with one
), because you're telling the reader that the algorithm only needs to know that one
is a car
, it doesn't need to know what kind of car it is.
More: It's necessary to understand that a variable has both a compile-time type and a runtime type. The compiler sees one
as a car
, because it doesn't know what kind of car
the variable will be at any given time. But the runtime type of both will be opel
. If you have a method mm
that is defined for car
, and then overridden for opel
, one.mm()
and two.mm()
will both call the same method. Once the compiler looks at the compile-time type and decides the call is legal, then which one gets called when the program is run depends on the runtime type.