ScreenCharacter
Class and
Its SubclassesLetter
class of the
previous chapter so that it works for any screen character, which can
be either a letter or a digit.
The applet that we are going to build up in this section
looks as follows:
When you press the button, a new randomly-chosen character (letter or digit) will appear on the screen with randomly chosen position and font size.
Classes form a hierarchy. For example, both letters and digits are characters that can be drawn on the computer screen. So, you can define
and the subclassesclass ScreenCharacter {...}
The keywordclass Letter extends ScreenCharacter {...} class Digits extends ScreenCharacter {...}
extends
is used to distinguish the subclass (child
class) and the superclass (parent class). If nothing is said about the
superclass (like we have done in the definition of the
ScreenCharacter
class), then Java automatically considers
it as a subclass of the Object
class.
So, with the above declarations you have constructed the following
class hierarchy.
The point is that all instance variables and methods that belong to the
ScreenCharacter
class are inherited by its subclasses so that
they need not be defined again. For example, if at the higher level the
ScreenCharacter
class look like
then the subclassesclass ScreenCharacter { String name; String fontname; int fontsize; int x, y; void draw(Graphics g) { g.setFont(new Font(fontname, Font.BOLD, fontsize)); g.drawString(name, x, y); } }
Letter
and Digit
do not have
to introduce these instance variables and method again.
By the way, if you are wondering why we chose the long name
ScreenCharacter
instead of Character
, the reason
is that the Java system already has a Character
class
built in (in the java.lang
package) and we
want to avoid name clashes.
The Letter
class can be introduced as
What distinguishes a letter from a character is that it is case sensitive: upper- and lowercase letters are possible. For digits case-sensitivity is not present. Above we have implemented theclass Letter extends ScreenCharacter { String letterCase; void setCase(String letterCase) { this.letterCase = letterCase; } String getCase() { return letterCase; } void toLowerCase() { letterCase = "lowercase"; name = name.toLowerCase(); } void toUpperCase() { letterCase = "uppercase"; name = name.toUpperCase(); } }
toUpperCase
and
toLowerCase
methods in terms of methods with
the same name in the String
class.
This will have the effect that we wish
if it comes to drawing the letter on the screen.
this
and super
this
in the setCase
method
mean? The answer is that the variable this
refers
to "this object", i.e.,
the current Letter
object that is receiving the call of
setCase
. So, this.letterCase
is the instance variable
of the Letter
object and this instance variable differs
from the argument that is also called letterCase
and that is used
in the definition of the setCase
method.
So,
in a method, the keyword this
refers to the
instance of the class for which the method was invoked.
In a similar way, the keyword this
can be used
in the very first statement in a constructor; then it will refer to another
constructor of the class. In the above Letter
class
we could have defined the following two constructors.
In the first constructor we call a constructor of the same class with explicit arguments. This second definition of aLetter() { this("a", 12, 0, 0, "lowercase"); } Letter(String name, int fontsize, int x, int y, String letterCase) { super(name, fontsize, x, y); this.letterCase = letterCase; }
Letter
constructor is called.
In the definition of the second constructor we use a similar language element:
the keyword super
is used to refer to a constructor of the immediate superclass of the
currect class. In our case,
a constructor of the ScreenCharacter
class is invoked.
As we see,
in a method, the keyword super
refers to the
object for which the method was invoked as an instance of the superclass
of the class in which the method appears.
Letter
Appletimport java.awt.*; class ScreenCharacter { String name; String fontname = "Helvetica"; int fontsize; int x,y; void translate(int a, int b) { x = x+a; y = y+b; } int randomNumber(int low, int high) { return ((int) (low + Math.random()*(high-low))); } void randomize() { x = randomNumber(20,100); y = randomNumber(40,120); fontsize = randomNumber(8,36); } void draw(Graphics g) { g.setFont(new Font(fontname, Font.BOLD, fontsize)); g.drawString(name, x, y); } }
class Letter extends ScreenCharacter { String charCase; Letter() { this("a", 12, 0, 0, "lowercase"); } Letter (String name, int fontsize, int x, int y, String charcase) { this.name = name; this.fontsize = fontsize; this.x = x; this.y = y; this.charcase = charcase; } void setCase(String charCase) { this.charCase = charCase; } String getCase() { return letterCase; } void toLowerCase() { letterCase = "lowercase"; name = name.toLowerCase(); } void toUpperCase() { letterCase = "uppercase"; name = name.toUpperCase(); } void randomize() { // random position and fontsize super.randomize(); // random name int i = randomNumber(0,25); name = "abcdefghijklmnopqrstuvwxyz".substring(i,i+1); // random case if (randomNumber(0,2) == 0) { toLowercase(); } else { toUppercase(); } } }
import java.applet.Applet; import java.awt.*; public class CaseSensitiveLetterApplet extends Applet { Letter c; public void init() { add(new Button("randomize")); c = new Letter(); // create default letter a c.randomize(); // choose random properties of letter } public boolean action(Event e, Object arg) { c.randomize(); // choose random properties of letter repaint(); return true; } public void paint(Graphics g) { c.draw(g); } }
ScreenCharacter
Appletclass Digit extends ScreenCharacter { Digit() { this("1", 12, 0, 0); } Digit(String name, int fontsize, int x, int y) { this.name = name; this.fontsize = fontsize; this.x = x; this.y = y; } int intValue(Digit d) { return(Integer.parseInt(d.name)); } void randomize() { // random position and fontsize super.randomize(); // random value int i = randomNumber(0,9); name = "0123456789".substring(i,i+1); } }
CaseSensitiveLetterApplet
. The only difference lies
in the random creation of a letter or a digit. The new lines of Java code
are highlighted below.
import java.applet.Applet; import java.awt.*; public class CharacterApplet extends Applet { ScreenCharacter c; public void init() { add(new Button("new character")); c = generateCharacter(); // create randomly a letter or a digit c.randomize(); // choose random properties of letter or digit } public boolean action(Event e, Object arg) { c = generateCharacter(); // recreate randomly a letter or a digit c.randomize(); // choose random properties of letter or digit repaint(); return true; } public void paint(Graphics g) { c.draw(g); } ScreenCharacter generateCharacter() { if ( 0 == (int) Math.round(Math.random())) { return (new Letter()); } else { return (new Digit()); } } }