Compile-time types
Run-time types and polymorphism
Constructor protocol
Private variables
When you declare a variable you are saying what kinds of values that variable can hold.
This also limits what you can do with that variable to only those things that you can do with that type.
public class Animal {
public void feed() { … }
}
public class Dog extends Animal {
public void walk() { … }
}
We can feed any kind of animal.
But we can only walk dogs.
Animal critter = …;
Can we walk whatever’s in this crate?
Dog critter = …;
How about what’s in here?
Animal animal = new Dog("Fido");
The compiler will check that Dog
is a subclass of
Animal
to make sure this is a safe assignment.
But it can't keep track of what animal
really is.
You've told it it’s an Animal
so that's all it keeps
track of.
Animal animal;
if (Math.random() < 0.5) {
animal = new Dog("Fido");
} else {
animal = new Rhinoceros();
}
The compiler can check that both Dog
and
Rhinoceros
are subclasses of Animal
so
either assignment is safe.
But there’s no point trying to guess what animal
is
going to be beyond an Animal
.
animal.walk()
No.
The compiler only knows that animal
is an
Animal
and Animal
doesn’t have a
walk
method.
The compiler just makes sure that every method call is legal. I.e.
if we call animal.feed()
there will be some
feed
method.
But once a program is running, the run-time type of the object, i.e. what class was actually used to construct the object, will determine which code is run.
Any method call to an non-static method can be thought of as sending a message to that object saying, “Do the thing.”
This is the essence of polymorphism. How any given object will respond to that message is determined by the actual class of the object, not by what the compiler knows about its type.
public class Eater {
public void eat(Food food) {
System.out.println("Nom nom nom.");
}
}
public class PickyEater extends Eater {
public void eat(Food food) {
System.out.println(isFavorite(food) ? "Yum" : "Yuck!");
}
}
Eater eater = someKindOfEater();
Compiler knows eater
is an Eater
. So this
is safe:
eater.eat(new Broccoli());
But at runtime it will be some particular kind of eater.
That runtime type will determine which
eat
method is called.
public class Dog {
public void act() {
System.out.println("run ");
eat(); // this is still a polymorphic call
}
public void eat() {
System.out.println("eat ");
}
}
The call to eat
in act
may run the method
defined in Dog
or it may not.
super.method()
This is not a polymorphic call. It always invokes the method found in the direct parent class of the class containing the call.
public class A {
public void foo() {...}
}
public class B extends A {
public void bar() {
super.foo(); // always invokes A's foo
foo(); // invokes foo from actual class of object
}
public void foo() {...}
}
public class C extends B {
public void foo() {...}
}
“You have the right to a constructor. If you do not do not write a constructor, one will be provided for you.”
All classes must have at least one constructor.
If you do not write a constructor, the compiler will add a no-argument constructor for you.
All constructors must, as the first thing they do, invoke a constructor from their parent class.
If a constructor does not explicitly invoke a parent constructor
with super
, the compiler will insert a call to
super()
, i.e. to a no-argument constructor.
A constructor in a class whose parent class does not have a no-arg constructor must explicitly invoke one of the constructors the parent class does have.
When extending a class without a no-arg constructor you will have to write a constructor in order to invoke one of the parent's constructors.
Remember that the job of a constructor is to make sure an object is properly initialized and ready to use.
These rules work to ensure that that stays true even in the face of inheritance.
Not much to say here. private
means private.
Subclasses can not directly reference private
variables
from their parent class.
Note that you can even have a variable in a subclass that is the same name as a private variable in the superclass. In such a case they are different variables.