GNU   davin.50webs.com/J.T.W
a GNU world order – your home of everything that is free

Main Menu Research Projects Photo Album Curriculum Vitae The Greatest Artists
Email Address Computer Games Web Design Java Training Wheels The Fly (A Story)
Political Activism Scruff the Cat My Life Story Smoking Cessation Other Links
Tutorial 1 Tutorial 2 Tutorial 3 Tutorial 4 Tutorial 5
Tutorial 6 Tutorial 7 Tutorial 8 Tutorial 9 Tutorial 10
Tutorial 11 Tutorial 12 Tutorial 13 Tutorial 14 Tutorial 15
Tutorial 16 Tutorial 17 Tutorial 18 Using Emacs Download Links


J.T.W. tutorial 15: Basic inheritance and polymorphism


§ 15 Tutorial 15


§ 15.1 Basic Inheritance

When you see the following code: class X extends Y, it means that class X inherits from the class Y. Class X is called the subclass and the class Y is called the super-class or sometimes the parent class. When the class X extends from 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.

Question 15.1: Study, compile and run the following code. The following code shows how inheritance works. In the following code, the Bird class inherits from the Animal class. The Bird class pulls in the Animal class's age property and the canFly and talk methods. Importantly the 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!

class Animal 
begin 

   property int age; // Animal's age in years 
   property int health; // Animal's health in hit points 

   constructor Animal() 
   begin 
      age    = 0; // NOTE: not needed as set by default 
      health = 100; 
   end 

   method boolean canFly() 
   begin 
      return false; 
   end 

   method void talk() 
   begin 
      System.out.println("Hello"); 
   end 
end 

class Bird extends Animal 
begin 

   property double flySpeed; // Bird's speed in km/h 

   constructor Bird() 
   begin 
      super();         // NOTE: not needed as called by default 
      flySpeed = 0; // NOTE: not needed as set by default 
   end 

   method boolean canFly() 
   begin 
      return true; 
   end 

   method void peck() 
   begin 
      System.out.println("peck"); 
   end 
end 

class InheriTest 
begin 
   beginMain 
      var Bird eagle = new Bird(); 
      eagle.talk(); 
      eagle.peck(); 
   endMain 
end 

Question 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.

Question 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: int numberOfKills and one method: void attack() that internally increments the value of numberOfKills. In the main function you should call every method of the Eagle class and its super-classes.

Question 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?

Question 15.5: Create a new class Kiwi that inherits from the Bird class. Your Kiwi class should override the 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 Kiwi class have a property numberOfWorms. Once you have written the Kiwi class you should create an instance of the Kiwi class in the main function.

Question 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?

System.out.println(k.health); 

Question 15.7: In the classes Animal, Bird, Eagle and Kiwi, remove all of the canFly methods and replace it with a single canFly property of the Animal class. In the constructors you will need to set the value of the canFly property to a value that is appropriate for that class. For example in the Bird class's constructor you should set the canFly property to true, while in the Kiwi class's constructor you should set the canFly property to false.

Question 15.8: What is the advantage of having a canFly property over a bunch of canFly METHODS?

There is an equally valid alternative to having a public property in the Animal class and that is to have in the Animal class a private property canFly and a pair of methods for getting and setting the value of the 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. Note that the canFly method of the code above corresponds to getCanFly method in the code below.

private property boolean canFly; 

method boolean getCanFly() 
begin 
   return canFly; 
end 

method void setCanFly(boolean aCanFly) 
begin 
   canFly = aCanFly; 
end 

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.

Question 15.9: Change the main function to what follows:

var Bird b = new Bird(10); 
var Animal a = b; 
a.talk(); 
a.peck(); 

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

Question 15.10: Change the main function to what follows:

var Animal a = new Animal();
var Bird b = a;
b.talk();
b.peck();

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


§ 15.2 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:

function void say(Animal a) 
begin 
   System.out.println(a instanceof Bird); 
end 

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 Bird object. Some examples should clarify the situation:

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.


§ 15.3 The super-class of all objects

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

Back to J.T.W
This page has the following hit count:
| Main Menu | Research Projects | Photo Album | Curriculum Vitae | The Greatest Artists |
| Email Address | Computer Games | Web Design | Java Training Wheels | The Fly (A Story) |
| Political Activism | Scruff the Cat | My Life Story | Smoking Cessation | Other Links |
| Tutorial 1 | Tutorial 2 | Tutorial 3 | Tutorial 4 | Tutorial 5 |
| Tutorial 6 | Tutorial 7 | Tutorial 8 | Tutorial 9 | Tutorial 10 |
| Tutorial 11 | Tutorial 12 | Tutorial 13 | Tutorial 14 | Tutorial 15 |
| Tutorial 16 | Tutorial 17 | Tutorial 18 | Using Emacs | Download Links
Last modified: Mon 15 Aug 2022 11:24:51 NZST
Best viewed at 1024x768 or above resolution.
© Copyright 1998-2022 Davin Pearson.
Please report any broken links to