
This tutorial shows you a practical example of inheritance. The file
TT(StarWars.jtw) is comprised of three classes: TT(XWing), TT(TieFighter) and
TT(StarWars). The first two represent spacecraft from the two sides of the
Star Wars films. The class TT(StarWars) is the driver class and contains
code for executing a battle between the X-Wings and the Tie Fighters.

@cindex Inheritance and removing duplication of code.

BO(Question 4.16.1:) Study, compile and run the following code:

@example
CLASS XWing
BEGIN

PD PRIVATE PROPERTY int     shields;
PD PRIVATE PROPERTY int     weapon;
PD PRIVATE PROPERTY boolean dead;

PD CONSTRUCTOR XWing()
PD BEGIN
PD PD shields = 1000;
PD PD weapon  = 10;
PD END

PD METHOD int getWeapon()
PD BEGIN
PD PD RETURN weapon;
PD END
PD METHOD boolean isDead()
PD BEGIN
PD PD RETURN dead;
PD END
PD METHOD void hit(int damage)
PD BEGIN
PD PD shields = shields - damage;
PD PD if (shields<0)
PD PD THEN BEGIN
PD PD PD System.out.println("BOOM!!!");
PD PD PD dead = TRUE;
PD PD END
PD END
END

CLASS TieFighter
BEGIN

PD PRIVATE PROPERTY int     shields;
PD PRIVATE PROPERTY int     weapon;
PD PRIVATE PROPERTY boolean dead;

PD CONSTRUCTOR TieFighter()
PD BEGIN
PD PD shields = 500;
PD PD weapon  = 20;
PD END

PD METHOD int getWeapon()
PD BEGIN
PD PD RETURN weapon;
PD END
PD METHOD boolean isDead()
PD BEGIN
PD PD RETURN dead;
PD END
PD METHOD void hit(int damage)
PD BEGIN
PD PD shields = shields - damage;
PD PD IF (shields<0)
PD PD THEN BEGIN
PD PD PD System.out.println("BOOM!!!");
PD PD PD dead = true;
PD PD END
PD END
END

CLASS StarWars
BEGIN

PD PRIVATE FUNCTION void duel(XWing x, TieFighter t)
PD BEGIN

PD PD for (;;)
PD PD BEGIN
PD PD PD x.hit(t.getWeapon());
PD PD PD IF (x.isDead())
PD PD PD THEN BEGIN
PD PD PD PD System.out.println("X-Wing is dead");
PD PD PD PD BREAK;
PD PD PD END
PD PD PD t.hit(x.getWeapon());
PD PD PD if (t.isDead())
PD PD PD THEN BEGIN
PD PD PD PD System.out.println("Tie Fighter is dead");
PD PD PD PD break;
PD PD PD END
PD PD END
PD END

PD PRIVATE FUNCTION void battle(XWing[] good, TieFighter[] evil)
PD BEGIN
PD PD VAR int g          = 0;
PD PD VAR int e          = 0;
PD PD VAR int goodDeaths = 0;
PD PD VAR int evilDeaths = 0;

PD PD WHILE (g<good.length and e<evil.length)
PD PD BEGIN
PD PD PD System.out.println("battling X-Wing #" + g + " versus Tie Fighter #" + e);
PD PD PD duel(good[g],evil[e]);
PD PD PD IF (good[g].isDead())
PD PD PD THEN BEGIN
PD PD PD PD g = g + 1;
PD PD PD PD goodDeaths = goodDeaths + 1;
PD PD PD END
PD PD PD IF (evil[e].isDead())
PD PD PD THEN BEGIN
PD PD PD PD e = e + 1;
PD PD PD PD evilDeaths = evilDeaths + 1;
PD PD PD END
PD PD END

PD PD VAR int finalGood = good.length - goodDeaths;
PD PD VAR int finalEvil = evil.length - evilDeaths;

PD PD System.out.println();
PD PD System.out.println("Battle Report: PD X-Wings PD Tie Fighters");
PD PD System.out.println("----------------------------------------------");
PD PD System.out.println();
PD PD System.out.println("Initial ships:" + good.length + "  " + evil.length);
PD PD System.out.println();
PD PD System.out.println("Killed ships:"  + goodDeaths  + "  " + evilDeaths);
PD PD System.out.println();
PD PD System.out.println("Final ships:"PD + finalGoodPD + "  " + finalEvil);
PD PD System.out.println();
PD PD IF (finalGood>finalEvil)
PD PD THEN BEGIN
PD PD PD System.out.println("The rebel alliance is victorious!");
PD PD END
PD PD ELSE BEGIN
PD PD PD System.out.println("The dark side has conquered!");
PD PD END
PD PD System.out.println();
PD END

PD BEGINMAIN
PD PD COMM(// defines the goodies array)
PD PD VAR XWing[] goodies = new XWing[3];
PD PD COMM(// initialises the elements of the goodies array)
PD PD SUPERFOR (VAR int i=0 TU goodies.length-1)
PD PD BEGIN
PD PD PD goodies[i] = new XWing();
PD PD END

PD PD COMM(// defines the baddies array)
PD PD VAR TieFighter[] baddies = new TieFighter[3];
PD PD COMM(// initialises the elements of the baddies array)
PD PD SUPERFOR (VAR int i=0 TU baddies.length-1)
PD PD BEGIN
PD PD PD baddies[i] = new TieFighter();
PD PD END

PD PD battle(goodies,baddies);

PD ENDMAIN
END
@end example

BO(Question 4.16.2:) Compile and run this file to see the battle between the
X-Wings and the Tie Fighters unfold.

BO(Question 4.16.3:) If you look at the Java code for the XWing and
TieFighter classes you will notice that they are almost identical:
They have the same methods and properties, the only difference is that
the TT(XWing) objects are initialized with a different value for their
TT(shields) and TT(weapon) properties to the TT(TieFighter) objects.

The next few questions will guide you through the process of using
inheritance to eliminate this unnecessary duplication of code. A new
class called SpaceShip will be created and all of the code that is
common to XWing and TieFighter will be moved into this class. The
XWing and TieFighter classes will then be modified so that they both
inherit from SpaceShip.

BO(Question 4.16.4:) The first step in this process is to create the outer
shell of the SpaceShip class, which you should now type in:

@example
CLASS SpaceShip
BEGIN
END
@end example

BO(Question 4.16.5:) Move the properties TT(shields), TT(weapon) and
TT(dead) out of the TT(XWing) and TT(TieFighter) classes and into the
TT(SpaceShip) CLASS. You must change the privacy status of the
properties from PRIVATE to PROTECTED. The protected modifier was
invented as an intermediate level of privacy between POBLIC and
PRIVATE. Like PRIVATE, it allows visibility to the same class in which
the method or property was defined, but unlike PRIVATE it also allows
visibility to sub-classes of the class in which the METHOD or PROPERTY
was defined.

BO(Question 4.16.6:) Move the three methods TT(getWeapon), TT(isDead) and
TT(hit) out of the TT(XWing) and TT(TieFighter) classses and into the
TT(SpaceShip) CLASS. At this point, the TT(XWing) and TT(TieFighter)
classes should contain nothing but a constructor.

BO(Question 4.16.7:) Finally, add the extends keyword to the first line of
the TT(XWing) and TT(TieFighter) classes:

@example
class XWing extends SpaceShip)
@end example

NI()and

@example
class TieFighter extends SpaceShip)
@end example

BO(Question 4.16.8:) Compile and run your program again, making sure that it
produces the same results now that it is using inheritance.

BO(Question 4.16.9:) The SpaceShip class is a super-class of both XWing and
TieFighter containing everything that X-Wings and Tie Fighters contain
in common. Because the role of the SpaceShip class is simply to hold
these commonalities, we might choose to label the class with the
abstract keyword:

@example
abstract class SpaceShip)
@end example

This prevents us from creating instances of the SpaceShip
class. Without the abstract modifier, we could happily create a new
SpaceShip(), which would be an object that is not an X-Wing, nor a Tie
Fighter, but just a vague "space ship". If we consider this to be a
logical mistake then we can use ABSTRACT to prevent such calls to the
SpaceShip constructor. Change the class SpaceShip to be ABSTRACT and
observe how the compiler will not accept any lines of the form:

@example
VAR SpaceShip s = new SpaceShip();) COMM(// compiler error)
@end example

NI()Remove the ABSTRACT keyword and notice how the compiler will then
allow this line to compile.
