home—info—lects—labs—exams—hws
tutor/PIs—breeze (snow day)
Object120 + its docs—java.lang docs—java.util docs
lect14a
inheritance: intro
and, course evals
Digsy the Dog goes "woof, woof".
Caleb the Cat goes "meow, meow".
Python the Python goes "ssss, ssss".
Phydeaux the Dog goes "yip, yip".
How would we represent the above?
Probably with a class Animal, whose fields are ...?
Whose methods are?
But what if we also wanted some methods
and fields specific to certain types of animals —
perhaps Cats have a field "clawSharpness" and
a method "pounce";
perhaps Dogs have a emthod "wagTail" (something that
pythons and cats are actually incapable of?
That's all well and good, but what
if we had then and other animals we wanted to model?
Say, cats and pythons, which both have ages and sounds,
and can getAge and speak …
but
we will still want separate classes, since some activities
are specific to Dogs
(perhaps getAgeInDogYears()).
One solution would be lots of repeated code for speak.
But (for the first time)1 we'll see what object-oriented programming buys for us:
the ability to share code between different (related) classes.
We will add a new class Animal,
and put the code which is common to all animals there.
Then, we will tell Java that class Cat extends Animal etc..
-
We get rid of the repeated code for speak,
and let all subclasses of Animal inherit the method speak.
Note:
If tomorrow we make class Griffin extends Animal,
it will automatically know how to speak()!
-
We also get rid of the repeated fields.
The fields are “inherited”, too.
-
What about the repeated code of initializing those fields, in the constructor?
We need the Cat constructor to call the general Animal constructor
(followed by any Cat-specific initialization, like claw-sharpness.)
-
extends, as in class B extends A:
we say that B is the “subclass”,
and
A is the “superclass”.
It means that an instance of B knows all the method
declarations and definitions which are in A.
We also say:
Every B “is-a” A.
Note the arrow in BlueJ — different from the “has-a”
(which uses a dotted line, and whose arrowhead isn't closed).
(click for .jar)
Animal.java, v1
Cat.java, v1
Python.java, v1
-
Call polymorphically (in an unsurprising way):
// Imagine this method in some other class entirely...
static String communicateHunger( Animal a ) {
return a.speak() + a.speak() + a.speak() + "!";
}
|
Note, incidentally, that we can call this method on either
a Cat,
or on
a Python.
This method doesn't know (and doesn't care),
what subclass of Animal it gets;
every Animal can speak, so
this method works just fine.
-
abstract:
If a superclass has been declared as an abstract class,
it means you can't have objects which are the supertype without
actually being some specific subtype.
That is: you can't call their constructor directly.
-
Constructor:
When constructing a Cat,
we need to initialize its fields.
But wait, isn't that repeated code, found in the superclass constructor?
Compare to class Python, to see the proper solution:
super is a keyword
to call the superclass constructor.
(The complete story on super is
below.)
This call should be the first line of your constructor
(if it isn't there, java rewrites your subclass constructor
so that it begins with the line super().
Note that if your superclass didn't have a 0-argument constructor,
this will generate an error.)
-
We've actually already seen inheritance:
all classes implicitly extend Object,
and every Object has the methods String toString()
and boolean equals(Object).
More on this in a moment.
-
We can add behavior specific to new classes;
for instance, perhaps Dogs can wagTail
(which Cats are simply not able to do).
(click for .jar)
Animal.java, v2
Cat.java, v2
Python.java, v2
Dog.java, v2
-
Overriding.
We can make Dog's speak method different from
all other Animals.
Call polymorphically (exciting! (?)):
if we call communicateHunger,
that method still doesn't know or care what type of Animal it gets;
moreover, it doesn't even know exactly which method will be called!
(That's okay -- the animal itself knows where it's code for speak is.)
-
Note that we've seen overriding already:
we've overriden toString.
Similarly, equals just uses == by default,
but some classes (like String)
have overridden equals to do something more specific.
Don't confuse “overriding” with the
much shallower concept, “overloading”.
-
(BTW:) Documenting overridding methods:
If you leave off javadoc for an method which overrides another,
the javadoc tool will grab the documentation from the original
super-version.
You can also use {@inheritDoc}
to “extend” the documentation with further,
more specific comments.
Some further reading, if you are interested:
some previous-semester's notes
and
notes, continued
1Every single
method we've written this semester could have been made static,
if we wanted!
We would just have to make one superficial change to each method:
add another parameter explicitly -- named this.
Then when calling the method, rather than saying mySavings.deposit(12.00),
we'd just have called deposit(mySavings, 12.00).
With this simple transformation, we could have done everything this semester
with static methods (though we'd still need non-static fields).
↩
home—info—lects—labs—exams—hws
tutor/PIs—breeze (snow day)
Object120 + its docs—java.lang docs—java.util docs