
SECT(Elementary classes: using a single class for everything)

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

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

@example
CLASS PersonDriver1
BEGIN
PD CLASSVAR String homersName = "Homer Simpson";
PD CLASSVAR int    homersAge  = 40; COMM(// Homer's age in years)

PD CLASSVAR String fredsName  = "Fred Flintstone";
PD CLASSVAR int    fredsAge   = 45; COMM(// Fred's age in years)

PD CLASSVAR String darthsName = "Darth Vader";
PD CLASSVAR int    darthsAge  = 55; COMM(// Darth's age in years)

PD FUNCTION void growHomer()
PD BEGIN
PD PD homersAge = homersAge + 1;
PD END
PD FUNCTION void growFred()
PD BEGIN
PD PD fredsAge = fredsAge + 1;
PD END
PD FUNCTION void growDarth()
PD BEGIN
PD PD darthsAge = darthsAge + 1;
PD END

PD FUNCTION void knightHomer()
PD BEGIN
PD PD homersName = "Sir " + homersName;
PD END
PD FUNCTION void knightFred()
PD BEGIN
PD PD fredsName = "Sir " + fredsName;
PD END
PD FUNCTION void knightDarth()
PD BEGIN
PD PD darthsName = "Sir " + darthsName;
PD END

PD FUNCTION void printHomer()
PD BEGIN
PD PD System.out.println("I am " + homersName + ", my age is " + homersAge);
PD END
PD FUNCTION void printFred()
PD BEGIN
PD PD System.out.println("I am " + fredsName + ", my age is " + fredsAge);
PD END
PD FUNCTION void printDarth()
PD BEGIN
PD PD System.out.println("I am " + darthsName + ", my age is " + darthsAge);
PD END

PD BEGINMAIN
PD PD growHomer();
PD PD knightHomer();
PD PD printHomer();
PD PD printFred();
PD PD printDarth();
PD ENDMAIN
END
@end example

BO(Question 4.9.2:) By copying the pattern established in the existing
code write a some new class variables to represent a new person called
Barak Obama.  Note that he was born August 4, 1961 so at the time of
writing this manual he is 54 years old.

m4_dnl (- 2016 1961)

BO(Question 4.9.3:) Then write some functions to work with this new person.

BO(Question 4.9.4:) Finally call those functions from the MAIN FUNCTION.

SECT(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.  The J.T.W.
programming language supports splitting a class into its constituent
methods and having one file for each method.  Simply use the INCLUDE
directive and J.T.W. will include the file for you like so:

TT(include "a.method";)

will include a method named TT(a).

BO(Question 4.9.5:) Study, compile and run the following code: Each of
these classes can be put in their own file. For each class TT(X), this
class can be put into a file called TT(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
TT(PersonDriver2.jtw)

@example
CLASS Homer
BEGIN
PD CLASSVAR String name = "Homer Simpson";
PD CLASSVAR int    age  = 40;) COMM(// Homer's age in years)

PD FUNCTION void grow()
PD BEGIN
PD PD age = age + 1;
PD END
PD FUNCTION void knight()
PD BEGIN
PD PD name = "Sir " + name;
PD END
PD FUNCTION void print()
PD BEGIN
PD PD System.out.println("I am " + name + ", my age is " + age);
PD END
END

CLASS Fred
BEGIN
PD CLASSVAR String name = "Fred Flintstone";
PD CLASSVAR int    age  = 45;) COMM(// Fred's age in years)

PD FUNCTION void grow()
PD BEGIN
PD PD age = age + 1;
PD END
PD FUNCTION void knight()
PD BEGIN
PD PD name = "Sir " + name;
PD END
PD FUNCTION void print()
PD BEGIN
PD PD System.out.println("I am " + name + ", my age is " + age);
PD END
END

CLASS Darth
BEGIN
PD CLASSVAR String name = "Darth Vader";
PD CLASSVAR int    age  = 55;) COMM(// Darth's age in years)

PD FUNCTION void grow()
PD BEGIN
PD PD age = age + 1;
PD END
PD FUNCTION void knight()
PD BEGIN
PD PD name = "Sir " + name;
PD END
PD FUNCTION void print()
PD BEGIN
PD PD System.out.println("I am " + name + ", my age is " + age);
PD END
END

CLASS PersonDriver2
BEGIN
PD BEGINMAIN
PD PD Homer.grow();
PD PD Fred.knight();
PD PD Homer.print();
PD PD Fred.print();
PD PD Darth.print();
PD ENDMAIN
END
@end example

BO(Question 4.9.6:) By copying the pattern established in the existing
code write a new class to represent Barak Obama.

BO(Question 4.9.7:) Call the functions from the MAIN FUNCTION of the driver
class.

SECT(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.

@cindex Mapping from class variables -> instance variables (also known as properties)
@cindex Mapping from functions -> methods

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

@example
CLASS Person
BEGIN )
PD COMM(/*
PD * NOTE: the use of the "property" keyword here instead of the
PD * "classVar" keyword.
PD */)
PD PROPERTY String name; COMM(// Person's full name)
PD PROPERTY int    age;  COMM(// Person's age in years)

PD COMM(/*
PD * NOTE: the use of the "method" keyword here instead of the
PD * "FUNCTION" keyword.
PD */)
PD METHOD void grow()
PD BEGIN
PD PD age = age + 1;
PD END

PD METHOD void knight()
PD BEGIN
PD PD name = "Sir " + name;
PD END

PD METHOD void print()
PD BEGIN
PD PD System.out.println("I am " + name + ", my age is " + age);
PD END

PD BEGINMAIN

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

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

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

PD PD h.grow();
PD PD h.knight();
PD PD h.print();
PD PD f.print();
PD PD d.print();
PD ENDMAIN
END
@end example

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

BO(Question 4.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 Barak Obama.

@cindex A common design pattern: PRIVATE properties, POBLIC constructor and POBLIC getters
@cindex Design pattern: PRIVATE properties, POBLIC constructor and POBLIC getters
@cindex PRIVATE properties, POBLIC constructor and POBLIC getters, a common design pattern

SECT(A common design pattern: PRIVATE properties, POBLIC CONSTRUCTOR and POBLIC getters)

@cindex Encapsulation

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.

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

@example
CLASS Person
BEGIN

PD PRIVATE PROPERTY String name;
PD PRIVATE PROPERTY int    age; COMM(// Age in years)
)
PD COMM(//)
PD COMM(// NOTE: Getter methods)
PD COMM(//)
PD POBLIC METHOD String getName()
PD BEGIN
PD PD return name;
PD END

PD POBLIC METHOD int getAge()
PD BEGIN
PD PD return age;
PD END

PD POBLIC CONSTRUCTOR Person(String aName, int anAge)
PD BEGIN
PD PD this.name = aName;
PD PD this.age  = anAge;
PD END

PD POBLIC METHOD void grow()
PD BEGIN
PD PD age = age + 1;
PD END

PD POBLIC METHOD void knight()
PD BEGIN
PD PD name = "Sir " + name;
PD END

PD POBLIC METHOD void print()
PD BEGIN
PD PD System.out.println("I am " + name + ", my age is " + age);
PD END
END

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

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

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

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

PD PD System.out.println("name=" + h.getName());  COMM(// OK: getter is non-private)
PD PD System.out.println("age="  + h.getAge());   COMM(// OK: getter is non-private)
PD ENDMAIN
END
@end example

Note that you will have to remove the error lines from the above file
for the code to compile.

BO(Question 4.9.11:) By copying the pattern established in the existing
code add some code to the MAIN FUNCTION to create a new person called
Hillary Clinton.  Hillary Clinton was born on October 26, 1947 so at
the time of writing this manual she was 68 years old m4_dnl (- 2016 1947)

SECT(Comparing strings)

BO(Question 4.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:

@example
FUNCTION boolean myCompare(String a, String b)
BEGIN
PD RETURN a == b;) COMM(// Works but not as expected!)
END
@end example

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:

@example
FUNCTION boolean myCompare(String a, String b)
BEGIN
PD return a.equals(b);
END
@end example

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 TT(String) class' substring and
(TT(toUpperCase) or TT(toLowerCase)) methods useful here too. See the
class STRING in the package TT(java.lang) at
@url{http://docs.oracle.com/javase/1.5.0/docs/api} for more details of
these two methods.

SECT(The NULL value for references)

@cindex 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.

@cindex The TT(toString) METHOD.
@cindex TT(toString) METHOD.

SECT(Why the toString method is better than any other method or
property for debugging)

@cindex TT(NullPointerException)

If x is a reference to a class TT(X) (including this for the current
class) and if TT(m) is a METHOD of TT(X) and TT(p) is a PROPERTY of
TT(X), and if TT(x) is currently NULL, then the following lines result in
a TT(NullPointerException) being thrown when executed:

@example
x.p;
x.m();
@end example

NI()whereas if TT(x) is NULL then

@example
TT(System.out.println(x);) and
TT(System.out.println("x=" + x);)
@end example

NI()prints out, respectively:

@example
NULL, and
x=NULL.
@end example

NI()If TT(x) is not NULL, it calls

@example
TT(System.out.println(x.toString());)
TT(System.out.println("x=" + x.toString());)
@end example

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

@example
POBLIC METHOD String toString()
BEGIN
PD COMM(// Code goes here...)
END
@end example

Importantly for reasons which will be explained later the toString
method must be declared with POBLIC 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:

@example
IF (x != NULL)
THEN BEGIN
PD System.out.println(x.p);
END
@end example

or like so for methods:

@example
IF (x != NULL)
THEN BEGIN
PD System.out.println(x.m());
END
@end example

Therefore the TT(toString) METHOD is more convenient than any other METHOD
or PROPERTY.

@cindex Why the TT(toString) method is better than any other METHOD or PROPERTY for debugging your code

BO(Question 4.9.13:) Change the TT(print) METHOD above from a METHOD that prints
out to the screen to a METHOD called TT(toString) that returns a
TT(String).

@cindex Writing your own methods

BO(Question 4.9.14:) Call the TT(toString) METHOD instead of the TT(print)
methods in the MAIN FUNCTION.
