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   Bob Dylan Quotes+       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 9: True O.O.P. classes


§ 9 Tutorial 9


§ 9.1 Elementary classes: using a single class for everything

For the purpose of the text that follows, O.O.P. stands for Object Oriented Programming.

Question 9.1: Study, compile and run the following code:

class PersonDriver1 
begin 
   classVar String homersName = "Homer Simpson"; 
   classVar int    homersAge  = 40; // Homer's age in years 

   classVar String fredsName  = "Fred Flintstone"; 
   classVar int    fredsAge   = 45; // Fred's age in years 

   classVar String darthsName = "Darth Vader"; 
   classVar int    darthsAge  = 55; // Darth's age in years 

   function void growHomer() 
   begin 
      homersAge = homersAge + 1; 
   end 
   function void growFred() 
   begin 
      fredsAge = fredsAge + 1; 
   end 
   function void growDarth() 
   begin 
      darthsAge = darthsAge + 1; 
   end 

   function void knightHomer() 
   begin 
      homersName = "Sir " + homersName; 
   end 
   function void knightFred() 
   begin 
      fredsName = "Sir " + fredsName; 
   end 
   function void knightDarth() 
   begin 
      darthsName = "Sir " + darthsName; 
   end 

   function void printHomer() 
   begin 
      System.out.println("I am " + homersName + ", my age is " + homersAge); 
   end 
   function void printFred() 
   begin 
      System.out.println("I am " + fredsName + ", my age is " + fredsAge); 
   end 
   function void printDarth() 
   begin 
      System.out.println("I am " + darthsName + ", my age is " + darthsAge); 
   end 

   beginMain 
      growHomer(); 
      knightHomer(); 
      printHomer(); 
      printFred(); 
      printDarth(); 
   endMain 
end 

Question 9.2: By copying the pattern established in the existing code write a some new class variables to represent a new person called Barack Obama. Note that he was born in 1945 so at the time of writing this manual he is 67 years old.

Question 9.3: Then write some functions to work with this new person.

Question 9.4: Finally call those functions from the main function.


§ 9.2 Improved classes: one object per class

As your program gets large (say over 1000 lines) then it becomes no longer practical to put all of your code in the same class. So it is natural to put each piece of related code in its own class.

Question 9.5: Study, compile and run the following code: Each of these classes can be put in their own file. For each class X, this class can be put into a file called X.jtw. However for the purposes of this tutorial you will probably find it easier to merge all of the classes into the same file into a file called PersonDriver2.jtw

class Homer 
begin 
   classVar String name = "Homer Simpson"; 
   classVar int    age  = 40; // Homer's age in years 

   function void grow() 
   begin 
      age = age + 1; 
   end 
   function void knight() 
   begin 
      name = "Sir " + name; 
   end 
   function void print() 
   begin 
      System.out.println("I am " + name + ", my age is " + age); 
   end 
end 

class Fred 
begin 
   classVar String name = "Fred Flintstone"; 
   classVar int    age  = 45; // Fred's age in years 

   function void grow() 
   begin 
      age = age + 1; 
   end 
   function void knight() 
   begin 
      name = "Sir " + name; 
   end 
   function void print() 
   begin 
      System.out.println("I am " + name + ", my age is " + age); 
   end 
end 

class Darth 
begin 
   classVar String name = "Darth Vader"; 
   classVar int    age  = 55; // Darth's age in years 

   function void grow() 
   begin 
      age = age + 1; 
   end 
   function void knight() 
   begin 
      name = "Sir " + name; 
   end 
   function void print() 
   begin 
      System.out.println("I am " + name + ", my age is " + age); 
   end 
end 

class PersonDriver2 
begin 
   beginMain 
      Homer.grow(); 
      Fred.knight(); 
      Homer.print(); 
      Fred.print(); 
      Darth.print(); 
   endMain 
end 

Question 9.6: By copying the pattern established in the existing code write a new class to represent Barack Obama.

Question 9.7: Call the functions from the main function of the driver class.


§ 9.3 True O.O.P.: more than one object per class

To allow for more than one object per class, most if not all class variables needs to be made into what are called instance variables (or more simply and more commonly known as properties) and most if not all functions need to be made into what are called methods.

Question 9.8: Study, compile and run the following code:

class Person 
begin 
   // 
   // NOTE: the use of the "property" keyword here instead of the "classVar" keyword 
   // 
   property String name; // Person's full name 
   property int    age;  // Person's age in years 

   // 
   // NOTE: the use of the "method" keyword here instead of the "function" keyword 
   // 
   method void grow() 
   begin 
      age = age + 1; 
   end 

   method void knight() 
   begin 
      name = "Sir " + name; 
   end 

   method void print() 
   begin 
      System.out.println("I am " + name + ", my age is " + age); 
   end 

   beginMain 

      var Person h = new Person(); 
      h.name = "Homer Simpson"; 
      h.age  = 40; 

      var Person f = new Person(); 
      f.name = "Fred Flintstone"; 
      f.age  = 45; 

      var Person d = new Person(); 
      d.name = "Darth Vader"; 
      d.age  = 55; 

      h.grow(); 
      h.knight(); 
      h.print(); 
      f.print(); 
      d.print(); 

   endMain 
end 

In the above code, note the use of three references h, f and

Question 9.9: By copying the pattern established in the existing code add some code to the main function add some code to create a new person for Barack Obama.


§ 9.4 A common design pattern: private properties, public constructor and public getters

A common design pattern in Java and one that I present for you in the following code is to make all of the properties of a class effectively read-only to all client classes by making all of the properties private and providing non-private getter methods for getting the values of the properties. It is possible for the original class to change the values of the properties but other classes (such as PersonTest below) are not capable of doing this, without calling a method of the original class such the grow and knight methods of the Person class. Finally an additional thing known as a constructor is used to ensure that objects are initialized with meaningful values for their properties.

Question 9.10: Study, compile and run the following code:

class Person 
begin 

   private property String name; 
   private property int    age; // Age in years 

   // 
   // NOTE: Getter methods 
   // 
   public method String getName() 
   begin 
      return name; 
   end 

   public method int getAge() 
   begin 
      return age; 
   end 

   public constructor Person(String aName, int anAge) 
   begin 
      this.name = aName; 
      this.age  = anAge; 
   end 

   public method void grow() 
   begin 
      age = age + 1; 
   end 

   public method void knight() 
   begin 
      name = "Sir " + name; 
   end 

   public method void print() 
   begin 
      System.out.println("I am " + name + ", my age is " + age); 
   end 
end 

class PersonDriver3 
begin 
   beginMain 

      // 
      // NOTE: In the following constructor calls the age and name are set by the constructor 
      // 
      var Person h = new Person("Homer Simpson",40); 
      var Person f = new Person("Fred Flintstone",45); 
      var Person d = new Person("Darth Vader",55); 

      h.grow(); 
      h.knight(); 
      h.print(); 
      f.print(); 
      d.print(); 

      h.name = "Luke Skywalker";                 // ERROR: name is private 
      h.age = h.age + 1;                         // ERROR: age is private 

      System.out.println("name=" + h.name);      // ERROR: name is private 
      System.out.println("age=" + h.age);        // ERROR: age is private 

      System.out.println("name=" + h.getName()); // OK: getter is non-private 
      System.out.println("age=" + h.getAge());   // OK: getter is non-private 

   endMain 
end 

Question 9.11: By copying the pattern established in the existing code add some code to the main function add some code to create a new person called Barack Obama.


§ 9.5 Comparing strings

Question 9.12: Add a method unknight() which removes the "Sir " title if he has one. One trap for young players in J.T.W. or Java is to use the operator == to compare strings like so:

function boolean myCompare(String a, String b) 
begin 
   return a == b; // Works but not as expected! 
end 

It compiles without error, but doesn't give you the result you were expecting. Instead you need to use the equals method of the String class like so:

function boolean myCompare(String a, String b) 
begin 
   return a.equals(b); 
end 

More generally, if x and y are a references to objects, then x == y returns whether or not x and y are pointing to the same object, whereas x.equals(y) returns whether or not the contents of the objects referred to by x and y are equal. The meaning of the word contents varies from class to class, but in the case of strings it means that the strings contain the same data.

You will also find the String class' substring and (toUpperCase or toLowerCase) methods useful here too. See the String class of the java.lang package in the following link:

http://docs.oracle.com/javase/1.5.0/docs/api

for more details of these two methods.


§ 9.6 The null value for references

As soon as you learn how to use references you need to know that all reference variables could conceivably hold the value null, meaning no value. In particular when properties are themselves references as you will discover in Tutorial 11, then those properties are initialized to null by default. Object arrays that you will learn about in Tutorial 10 using the second of two initialization syntaxes are also initialized to null by default.


§ 9.7 Why the toString method is better than any other method or property for debugging

If x is a reference to a class X (including this) and if m is a method of X and p is a property of X, and if x is currently null, then the following lines result in a NullPointerException being thrown when executed:

x.p; 
x.m(); 

whereas if x is null then

prints out, respectively:

If x is not null, it calls

so these expressions are safer to use than any other method or property in situations where x might be null. The syntax of the toString method is as follows:

public method String toString() 
begin 
   // Code goes here... 
end 

Importantly for reasons which will be explained later the toString method must be declared with public visibility. For other properties and methods to be used safely with null references you need to wrap a conditional if construct around the calling of the method or property like so for properties:

if (x != null) 
then begin 
   System.out.println(x.p); 
end 

or like so for methods:

if (x != null) 
then begin 
   System.out.println(x.m()); 
end 

Therefore the toString method is more convenient than any other method or property. Note that its use is without the explicit call to the toString method and only used with a variable name, including this for the current class. Most of the time the this keyword is optional which is why novices don't bother to learn it, but in the case of the toString method it is essential, as can be seen in the following example code:

System.out.println("x.toString()="    + x);
System.out.println("this.toString()=" + this);

Question 9.13: Change the print method above from a method that prints out to the screen to a method called toString that returns a string.

Question 9.14: Call the toString method instead of the print methods in the main function.

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 | Bob Dylan Quotes+ | 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: Tue Apr 18 20:33:47 NZST 2017
Best viewed at 800x600 or above resolution.
© Copyright 1999-2017 Davin Pearson.
Please report any broken links to