SECT(Basic Inheritance)

@cindex Inheritance

When you see the following code: CLASS TT(X) extends TT(Y), it means
that CLASS TT(X) inherits from the CLASS TT(Y). Class TT(X) is called
the subclass and the CLASS TT(Y) is called the super-class or sometimes the
parent CLASS. When the class TT(X) extends from TT(Y), it pulls in all of the
non-private methods and properties from the super-class Y. Inherited
methods can override the behaviour of that same method in the
super-class to give behaviour that is specific to the subclass. The
concept of methods overriding other methods is called dynamic method
binding or more commonly the more impressive-sounding name:
polymorphism. The main thing that this tutorial shows is the idea that
inheritance is a non-symmetrical relationship. For example: in the
code that follows, the Bird class inherits from the Animal class,
which corresponds to the idea that every bird is an animal. The
reverse, every animal is a bird is plainly not true! Inheritance
forces you to recognize this.

BO(Question 4.15.1:) Study, compile and run the following code. The
following code shows how inheritance works. In the following code, the
TT(Bird) CLASS inherits from the TT(Animal) CLASS. The TT(Bird) CLASS pulls in
the Animal class's TT(age) property and the TT(canFly) and TT(talk)
methods. Importantly the TT(canFly) property overrides the behaviour of
the canFly method of the parent Animal class, which reflects that fact
that generally speaking, birds can fly. In the code that follows, note
that int properties are initialized to zero by default and the super
method (also known as the constructor of the super-class) is called by
default if there is a zero parameter constructor in the super-class,
which there is by default, even if you don't write one!

@example
CLASS Animal
BEGIN

PD PROPERTY int age;    COMM(// Animal's age in years)
PD PROPERTY int health; COMM(// Animal's health in hit points)

PD CONSTRUCTOR Animal()
PD BEGIN
PD PD age    = 0; COMM(// NOTE: not needed as set by default)
PD PD health = 100;
PD END

PD METHOD boolean canFly()
PD BEGIN
PD PD return FALSE;
PD END

PD METHOD void talk()
PD BEGIN
PD PD System.out.println("Hello");
PD END
END

CLASS Bird extends Animal
BEGIN

PD PROPERTY double flySpeed;) COMM(// Bird's speed in km/h)

PD CONSTRUCTOR Bird()
PD BEGIN
PD PD super();      COMM(// NOTE: not needed as called by default)
PD PD flySpeed = 0; COMM(// NOTE: not needed as set by default)
PD END

PD METHOD boolean canFly()
PD BEGIN
PD PD RETURN TRUE;
PD END

PD METHOD void peck()
PD BEGIN
PD PD System.out.println("peck");
PD END
END

CLASS InheriTest
BEGIN
PD BEGINMAIN
PD PD VAR Bird eagle = new Bird();
PD PD eagle.talk();
PD PD eagle.peck();
PD ENDMAIN
END
@end example

BO(Question 4.15.2:) Override the talk method of the Animal class in the
Bird class to print out ``Tweet Tweet!'' rather than ``hello'' to give
more accurate talking of bird objects.

BO(Question 4.15.3:) By copying the pattern established in the Bird class,
change the eagle from an instance of the Bird class to its own class
in its own right and then create an instance of that class in the MAIN
FUNCTION of InheriTest. Your Eagle class should have one PROPERTY: TT(int
numberOfKills) and one METHOD: TT(void attack()) that internally increments
the value of TT(numberOfKills). In the MAIN FUNCTION you should call every
method of the Eagle class and its super-classes.

BO(Question 4.15.4:) What is the advantage of using a new separate class to
represent a new object rather than using an instance of an existing
class?

@cindex Writing your own classes

BO(Question 4.15.5:) Create a new CLASS TT(Kiwi) that inherits from the
TT(Bird) CLASS. Your TT(Kiwi) CLASS should override the TT(canFly)
method to return FALSE, which reflects the fact that generally
speaking birds can fly, but the kiwi bird in particular does not
fly. Your TT(Kiwi) CLASS have a PROPERTY TT(numberOfWorms). Once you
have written the TT(Kiwi) CLASS you should create an instance of the
TT(Kiwi) CLASS in the MAIN FUNCTION.

BO(Question 4.15.6:) Why does the following line of code in the MAIN
FUNCTION print out 100 but there is no setting of that variable to
that value in the Kiwi class?

@example
System.out.println(k.health);
@end example

BO(Question 4.15.7:) In the classes TT(Animal), TT(Bird), TT(Eagle) and
TT(Kiwi), remove all of the TT(canFly) methods and replace it with a
single TT(canFly) property of the Animal class. In the constructors
you will need to set the value of the TT(canFly) PROPERTY to a value
that is appropriate for that class. For example in the TT(Bird)
class's constructor you should set the TT(canFly) PROPERTY to TRUE,
while in the TT(Kiwi) CLASS's constructor you should set the
TT(canFly) PROPERTY to FALSE.

BO(Question 4.15.8:) What is the advantage of having a TT(canFly)
PROPERTY over a bunch of TT(canFly) methods?

There is an equally valid alternative to having a POBLIC PROPERTY in
the TT(Animal) CLASS and that is to have in the TT(Animal) CLASS a
PRIVATE PROPERTY TT(canFly) and a pair of methods for getting and
setting the value of the TT(canFly) property like so. These methods in
J.T.W. and Java are called getter methods and setter methods since, as
their names suggest, getters are used for getting the value of
something and setters are used for setting the value of
something. Nore that the TT(canFly) METHOD of the code above
corresponds to TT(getCanFly) METHOD in the code below.

@example
PRIVATE PROPERTY boolean canFly;

METHOD boolean getCanFly()
BEGIN
PD RETURN canFly;
END

METHOD void setCanFly(boolean aCanFly)
BEGIN
PD canFly = aCanFly;
END
@end example

@cindex Getter and setter methods
@cindex Setter and getter methods

You might think that it is simpler to have one thing (a single
non-private property) rather than three things (a private property and
a non-private getter method and a non-private setter method) and you
would be right. However from the point of view of the client code that
uses the Animal CLASS, the two approaches are identical. Later on when
you learn more you will understand under what circumstances the second
getter and setter approach is better.

BO(Question 4.15.9:) Change the MAIN FUNCTION to what follows:

@example
BEGINMAIN
PD VAR Bird b = new Bird(10);
PD VAR Animal a = b;
PD a.talk();
PD a.peck();
ENDMAIN
@end example

When you compile this code it gives a compilation error. What line
gives the error and what is the reason for the error?

BO(Question 4.15.10:) Change the MAIN FUNCTION to what follows:

@example
BEGINMAIN
PD VAR Animal a = new Animal();
PD VAR Bird b = a;
PD b.talk();
PD b.peck();
ENDMAIN
@end example

When you compile this code it gives a compilation error. What line
gives the error and what is the reason for the error?

SECT(Run-time type inquiry)

In J.T.W. and Java there is a keyword called INSTANCEOF that does
a run-time check on the type of an object. The following FUNCTION:

@example
FUNCTION void say(Animal a)
BEGIN
PD System.out.println(a instanceof Bird);
END
@end example

uses the INSTANCEOF keyword to determine the run-time type of the
reference a and prints out whether or not the reference is referring
to a TT(Bird) object. Some examples should clarify the situation:

@cindex INSTANCEOF keyword

@itemize @bullet
@item TT(say(new Bird())) prints TRUE, Since the parameter a is pointing to a bird object at run-time,
@item TT(say(new Animal())) prints FALSE since not every animal is a bird,
@item TT(say(new Eagle())) prints TRUE, since every eagle is a bird, and
@item TT(say(new Kiwi())) prints TRUE, since every kiwi is a bird.
@item TT(VAR Animal a = new Animal(); say(a);) prints FALSE since at run-time a is not pointing to a bird object
@item TT(VAR Animal a = new Bird(); say(a);) prints TRUE since at run-time a is pointing to a bird object.
@end itemize

In Tutorial 17 you will learn why in most cases it is better to use
polymorphism instead of the instanceof keyword for run-time type
enquiry.

SECT(The superclass of all objects)
@cindex TT(Object) superclass of all objects

Every CLASS in Java inherits either directly or indirectly from a
CLASS called TT(Object). That is to say if TT(x) is a reference
variable, then the run-time expression TT(x instanceof Object) is
always TRUE except for the pathological case where TT(x) is NULL
(i.e. is currently pointing to no object). The TT(Object) CLASS
contains a method called TT(toString) that returns a string containing
the run-time CLASS name of the object concatenated with the hash code
of the memory address of the object in base 16 (also known as
hexadecimal) format. Since every CLASS inherits from Object, every
object can have TT(toString) invoked upon it. Even better, every CLASS
TT(X) can override TT(toString) to provide debugging information that
is tailored to TT(X). Therefore the TT(toString) METHOD is convenient
for debugging. Since the TT(toString) METHOD is a POBLIC METHOD of the
TT(Object) CLASS it must be overridden as a POBLIC method, since your
overridden FUNCTION cannot have weaker access privileges.

@cindex The TT(toString) method and its usefulness in debugging.
