Sie sind auf Seite 1von 53

Chapter 7.

Inheritance and Interfaces

Context

The purpose of this unit is to introduce the implementation of inheritance in Java.


Inheritance is a key feature of the object-oriented approach to software development.
This unit also introduces Java interfaces, a limited form of inheritance that is widely
used in Java programming. Some common UML (Unified Modelling Language) symbols
are presented for notating inheritance relationships.

Objectives

At the end of this unit you will be able to

 explain what is meant by inheritance, multiple inheritance and interface


 construct a graphical model of a class hierarchy
 implement programs that exploit inheritance and polymorphism

Study Planning

You should expect to spend approximately 9 hours studying this unit. You may find it
convenient to break up your study as follows:

Disk-based Content: 2¼
hours
Application: 3 hours
Set textbook Content: 1 hour
Reflection (On-line discussions, review 1 hour
questions):
Tutorial Work: 1 hour
Related Coursework: ¼ hour
Extension Work: ½ hour

Equipment/software required

 Sun Java 2 Platform (also known as Java Development Kit 1.3)


 TextPad 4.5
 A Web browser

Reading material & resourses

Core texts (supplied with module material):

1. Java: how to program. H. M. Deitel and P. J. Deitel, 3rd edition, Prentice-Hall, ISBN: 0-
13-012507-5

Online Resources:

1. Frequently-asked questions
2. Additional Source Code Examples

Introduction to unit 7

This is an important unit, since inheritance, and its implementation in Java via the extends,
interface and abstract keywords is something that almost all non-trivial Java programs
exploit.

After working through this module you may wish to return to earlier units to examine the
Java listings with a view to identifying the extent to which each embodies inheritance.
Examples include the listings for the CircleSquare application you used in unit 1, and the
development of the bouncing ball application in unit 2.

The Deitel & Deitel book provides much reference material on Java's implementation of
inheritance, and in the extension sesof this unit you are directed towards Sun's website
for additional sources of reference.

Inheritance — Assigned reading

Java: how to program. H. M. Deitel and P. J. Deitel, 3rd edtion,


Prentice-Hall, ISBN: 0-13-012507-5 sections 9.1-9.18 pp 358-427 of
Chapter 9
Introduction to inheritance

Inheritance is a key feature of object-oriented programming It embodies the idea that one
thing is `like' (or a `type of') another thing. Inheritance is implemented in Java using the
extends and implements mechanisms.

Here is a simple example. Suppose we are writing a computer program that allows the
user to draw diagrams. It understands rectangles, circles, lines and text. We could write
sections of program to handle each of these shapes, but if we did this we would soon find
that we were writing the same program lines over and over again.

Why? Because all these shapes have a lot in common. All have one or more lines with a
particular thickness and colour. All can be filled in with, perhaps, a different colour. All
have a particular position on the screen, and so on. However, there are also differences
between the different shapes. For example, the idea of `font' (typeface) is meaningful for
text, but has no meaning for a line or circle.

The way inheritance works is that we define a class (perhaps called Shape) that contains
all the program instructions. Then we define classes for each of the other shapes, which
contain only the instructions that are necessary for that particular shape. So in the class
`Text' (for example) that handles the drawing of text, we would include instructions for
processing different typefaces.

Inheritance terminology and symbols

The class from which another class inherits is called its direct superclass or base class .
A class that does the inheriting is called the subclass or derived class.

The process of inheritances is also called specialization. The UML symbol for inheritance
is a large arrow pointing from the subclass to the base class, as shown below:

In UML notation, the figure below shows the notion that the class Car is a subclass of
Vehicle .
It is rather unfortunate that there is a lot of terminology associated with the concept of
inheritance. Very often there are different terms that mean the same thing. Object-
oriented programming is a widely-used, rapidly developing technique, and it is not
surprising that the terminology cannot be standardised as fast as the subject develops.

The relationships between classes can often be expressed more clearly on a diagram
than in text. The standard notation for this is called UML (unified modelling language).
The full UML specification is very long (currently 645 pages!), but will only require a few
symbols for this unit.

The classes are shown as rectangles. There are spaces in each class to write the
attributes and operations of that class. Remember, UML is a modelling language, so the
use of object-oriented modelling terms such as attribute and operation are used. A Java
programmer can take a model expression in UML and implement the model, so that the
modelled attributes and operations become appropriate variables and methods.

In the example above there aren't any attributes or operations, so these spaces are blank.
The large arrow denotes an inheritance relationship. This can be read as `Car is a
subclass of Vehicle', `Car is a type of Vehicle', `Car is a specialization of vehicle' or
`Vehicle is a base class for Car'.

Java keyword ‘extends’

In Java, the keyword extends denotes full inheritance. If a definition states that a new
class 'extends' another, this new class will inherits all the non-private methods (and
variables) of the class it extends

To change a method in some way is called overriding the method.

For example, suppose the class Shape has a method called draw() . If we define Line
as being a type of Shape as below:

class Line extends Shape


{
// variables (none at present)
// methods (none at present)
}
This means that class Line is a direct subclass of class Shape .

Then we could issue the instructions:

Line aLine = new Line();


aLine.draw();
this would send a message to the object aLine , which will invoke the draw() method
in Shape , because we have not defined a draw() method for Line (in fact, we have
not defined any methods for Line !)
However, we now define a draw method in the class Line ,
class Line extends Shape
{
public void draw()
{
// some actions to draw a line
}
// other methods go here...
}
When we do:
aLine.draw()
this message will result in the invocation of the draw() method defined in class Line ,
not the one in Shape . Thus we have overridden the inherited method Shape.draw()
in the class Line .

Indirect inheritance

Indirect inheritance embodies the idea that one thing is a type of another thing, and that
thing is in turn a type of something else. For example, if C is a subclass of B , and B is a
subclass of A , then C is an indirect subclass of A . Indirect inheritance is handled
automatically in Java.

Such relationships are illustrated in this diagram:

To extend the example above a little, suppose that we define a class called Moveable
that describes how to make an object moveable on the screen (in any useful drawing
program we would need to be able to move shapes around). But as well as moving
Shapes, suppose we have other moveable items (like gridlines or markers on the
screen). So a Gridline is a type of Moveable , while a Line and a Circle are
types of Shape , which is a type of Moveable . The outline of the Java program that
defines these relationships might be:

class Moveable
{
// methods that define the class Moveable
}
class Shape extends Moveable
{
// methods that define the class Shape, that are not
// included in class Moveable
}
class Circle extends Shape
{
// methods that define the class Circle, that are not
// included in class Moveable or class Shape
}

Multiple inheritance

 Multiple inheritance embodies the idea that one thing is a type of more than one
other thing
 True multiple inheritance is not handled in Java
 Java supports something called `lightweight' multiple inheritance

In the previous example, Circle was a type of Shape , which was itself a type of
Moveable . These classes form a hierarchy with Moveable at the `top' and Circle at
the `bottom'. Circle was only indirectly a type of Moveable. Suppose we want to state
that a class is a direct subclass of two others. Here is an example. Suppose any object
that can receive input from the user is a subclass of KeyboardListener . Examples
might include buttons, menus, window borders, etc. Suppose

any object that can be displayed in a window is a subclass of Component (this is a real
Java entity, and will be described in more detail later).

Suppose we now define a class called MyButton which displays a button in a window.
This is a subclass of KeyboardListener (because we can activate the button by
pressing the space bar, or clicking the mouse). It is a subclass of Component because it
can be displayed in a window. But Component is not a subclass of
KeyboardListener . Why? Because there may be other classes that can be
displayed in a window, but cannot receive input (e.g., an icon, or an image). So these
classes do not form a hierarchy. MyButton is a subclass of both KeyboardListener
and Component.

You might think we could describe this in Java using something like:

class MyButton extends Component, KeyboardListener


{
// methods go here
}
But this won't work. Java does not support multiple inheritance . The debate about
whether multiple inheritance should be allowed in programming has been going on for a
long time, and is not yet settled. Whether it is a good thing or a bad, the Java
developers decided not to allow multiple inheritance in Java. You will have an
opportunity to make your own mind up about the correctness of this decision later.

Java does, however, support something called ' lightweight' multiple inheritance , using
interfaces .

Inheritance — Activities and Exercises

Activity 1 — MyCircle and MySquare extensions of MyShape

Exercise 1 — Inheritance Summary

Exercise 2 – UML-to-Java

Exercise 3 — Java-to-UML A

Exercise 4 — Multiple inheritance

Stop!
Before you go any further, be absolutely certain that you understand the information
presented so far. The rest of the unit, and indeed the rest of the module, will make no
sense at all if you do understand.

Interfaces — Assigned reading

Java: how to program. H. M. Deitel and P. J. Deitel, 3rd edition, Prentice-


Hall, ISBN: 0-13-012507-5 0. Read section 9.19 pp 427-432 of Chapter 9

Interfaces — templates for classes


An interface is a class that declares methods, but does not define them. This means that
the class contains no real program instructions. It exists only to take part in a subclass-
base class relationship

The concept of an interface can initially be conceptually difficult. You may have to go over
the next few sections several times to be sure you understand.

In the multiple inheritance example, we wanted MyButton to be a subclass of both


Component and KeyboardListene r . This was not allowed, because Java does not
support multiple inheritance. However, if we define either Component or
KeyboardListener as an interface (not a true class) then we can define MyButton to
inherit from both.

But the use of interfaces is only an organisational feature; an interface cannot contain
any program instructions. It is not really obvious which of the two entities (
KeyboardListener or Component ) should be an interface and which a class. In reality,
Component is very complex, and is defined as a class, while KeyboardListener (which
only has a few methods) is defined as an interface.

But if KeyboardListener is defined as having methods, and it cannot implement them


itself (because it is an interface, not a class), where are these methods implemented? In
this case they must be implemented in MyButton (which is a `subclass' of
KeyboardListener ). This will be illustrated below.

Defining an interface

An interface is defined just like a class, but with the `interface' keyword rather than the
`class' keyword. The methods must be defined, but not implemented

For example, the KeyboardListener interface may be defined like this:

interface KeyboardListener
{
void keyPressed();
void keyReleased();
}
We have said that the KeyboardListener has two methods: keyPressed() and
keyReleased() but we have not said how these methods are to be carried out. My
intention is that keyPressed() will be called whenever the user presses a key, and
keyReleased() when the key is released.

Implementing an interface — keyword 'implements'


The keyword 'implements' denotes inheritance from an interface, in the same way that
'extends' denotes inheritance from a class. A class can implement any number of
interfaces. The class must provide an implementation for all the methods specified by
the interface

Continuing the example above, if Compoment is a class, and KeyboardListener is


an interface, then we specify that MyButton is a type of Component and a type of
KeyboardListener as follows:

class MyButton extends Component implements


KeyboardListener
{
void keyPressed()
{
// instructions describing what to do when a key
is
// pressed
}
void keyReleased()
{
// instructions describing what to do when a key
is
// released
}
}
Note that the implementation of MyButton includes implementations of the methods `
keyPressed() ' and ` keyReleased()' as specified in the keyboardListener
interface.

What have we gained by using interfaces?

Interfaces do not provide `real' multiple inheritance. They provide an approximation to it


for simple classes. They help to organise a complex program.

The use of interfaces seems quite complicated at first, and the student can't be blamed
for wondering whether their use gives any real benefits. The importance of interfaces
becomes apparent when programs become more complicated. Suppose I define a
method in Java like this:

void doSomething(Object someObject)


{
someObject.keyPressed();
}
This method does not know what kind of object will be passed into it. It could be
anything. For this method to succeed, the class of which someObject is a member
must be defined to have a method called keyPressed() . At what point will the Java
system check whether this is the case or not? The Java run-time engine could easily
check when the program is executing, and call the method if it is, or abort the program if
it is not. But it would be nice to be able to write the program in such a way that we found
out potential errors very quickly. The way to do this is as follows:
void doSomething(KeyboardListener someObject)
{
someObject.keyPressed();
}
Now any object that implements the KeyboardListener interface can be passed to
this method, and anything else will be rejected. So if I write
MyButton newButton = new MyButton();
SomeMethod (newButton);
This will be fine, because MyButton implements the interface KeyboardListener .
On the other hand, if I (accidentally) try to pass an object of class Component (for
example) to this method, e.g.,
Component newButton = new Component();
SomeMethod (newButton);
it will be rejected immediately by the compiler.

Even though the use of interfaces does not limit the amount of program code the
programmer has to write, it does prevent the programmer making trivial errors that
cannot be detected by the compiler. It also help to clarify the structure of the program,
making it easier to maintain and update.

Over-riding methods and constructors

Providing a method in a subclass with the same name (and parameters) as in its base
class is called overriding the method. The subclass method takes precedence over the
base class method. This is usually the desired effect, except in constructors. The super
method invokes the base class constructor.

Suppose I define a class called Button, which displays a button on the screen. The
button is (for example) grey. The user can click the button and cause the program to
carry out an action. The Button has a method called paint() which causes it to
update its screen display. Now suppose I want to create a coloured button. Let's call this
class ColouredButton . A ColouredButton is exactly the same as a Button
except that :

 the paint() method paints a coloured button rather than a grey one, and
 when we create a ColouredButton we want to specify its colour

So to create an ordinary button we might write:


Button myButton = new Button ("OK");
and for a coloured button we might write
ColouredButton myButton = new ColouredButton ("OK",
Color.red);
So I will define my class ColouredButton something like this:
class ColouredButton extends Button
{
Color thisButtonColour;
// constructor
public ColouredButton(String text, Color colour)
{
thisButtonColour = colour;
// What do we do with `text'?
}
public void paint(Graphics g)
{
// Statements to draw the button in the new
colour
}

In the constructor for ColouredButton we save the specified colour in a variable so


that the paint() method can use it to determine what colour to draw the display in.
However, what do we do with the `text' argument? This defines the text that will appear
on the button. Now we could save this as an variable for later use, but this would be
inefficient, since the class Button also has text, so the Button base class of
ColouredButton probably needs to know what text is being displayed as well.

If I had created a new Button object, I would have written:

Button myButton = new Button ("OK");


This indicates that the constructor for Button handles the text that the button will display.
But in ColouredButton we have over-ridden the constructor with a new constructor.
Normally when we over-ride a method we want the new method to replace the old one.
However, with constructors we usually want the new constructor to add to the old one.

Java has a keyword for this: super . This means `call the constructor for this class's
super (base) class'. The super constructor takes the same arguments that the
constructor itself would take. So in the Button example, when we call super in the
ColouredButton constructor, we specify the text of the button just as if we were
creating a new Button object. So the constructor for ColouredButton becomes:

public ColouredButton(String text, Color colour)


{
super(text); // call base class constructor
thisButtonColour = colour;
}

If you create a subclass of a class that was not written by yourself (e.g., one of Java's
many built-in classes), it is good practice to call super at the start of any constructor that
your new class over-rides. This will ensure that the base class is initialised correctly.
Failure to do this in Java leads to all sorts of bizarre errors which are hard to detect.

Recall of RandomBall method overriding

For another example of method overriding and inheritance look back at the unit 2 class
RandomBall , (in version 8 of the bouncing ball world) which overrode the move()
method to be random:

// RandomBall.java
public class RandomBall extends Ball
{
public RandomBall (int newX, int newY, int
newRadius,int newXMotion, int newYMotion)
{
// call the Ball constructor
super( newX, newY, newRadius, newXMotion,
newYMotion );
}
public void move()
{
// 50% chance of chaning X motion
if( Math.random() > 0.5 )
dx = -dx;
// 50% chance of changing Y motion
if( Math.random() > 0.5 )
dy = -dy;
// move centre of object
x = x + dx;
y = y + dy;
}
}
// class RandomBall

Abstract methods

 Abstract methods are those that must be overridden in a subclass


 If any methods are abstract, then the class is abstract
 An abstract class cannot be instantiated (that is, no objects of that class can be
created)

The word `abstract' here has no connection at all with the normal meaning of the word
(e.g., `abstract art'). An abstract class is one for which no objects can exist. Here is an
example. Circles , Squares and Lines are Types of Shape . Any shape can be
drawn, so it is sensible for the Shape class to have a draw() method. However, a
Shape object itself cannot exist; only its subclasses Circle , Square and Line
can have real objects. So although Shape has a draw() method, this method is
abstract, as is the class itself. We might define the Shape class something like this:
abstract class Shape
{
// Shape variables go here
public abstract void draw();
}
The following line of Java :
Shape myShape = new Shape();

will produce an error message to the effect that Shape is abstract and cannot be
instantiated.
When we create the subclasses, they must provide draw() methods, because the
Shape class is abstract due to the abstract method draw().

Inheritance and Interfaces concept map

As with the concept map from the earlier units, you can use the map below as a way
retrieve glossary entries. You might wish to re-visit this concept map (and perhaps
create / extend it for yourself on paper) as you progress through the module.
Activities

Activity 1 — MyCircle and MySquare extensions of MyShape

A class has been defined called MyShape. This class has the following variables and
methods:

class MyShape

Variables Methods

Public int xPos

Public int yPos

Public MyShape()

Public void setX( int newX )

Public void setY( int newY )


See the listing of MyShape.java.

Look at this listing for ShapeApplet.java:

import java.applet.Applet;
import java.awt.*;
public class ShapeApplet extends Applet
{
MyCircle shape1;
MySquare shape2;

public void paint( Graphics g )


{
shape1 = new MyCircle();
shape1.setX(100);
shape1.draw( g );
shape2 = new MySquare();
shape2.setY(20);
shape2.draw( g );
}
}

You need to define 2 new classes, called MyCircle and MyClass that both are direct
subclasses of MyShape . Each class should have a constructor method (setting initial values to
appropriate instance variable such as radius for the circle and sideLenth for the square),
and should also define a draw( Garphics g ) method that makes use of the inherited xPos
and yPos instance variables.

You can use the file Shape.html to load the applet into the appletviewer.

Discussion/Suggested solution to Activity 1

MyCircle and MySquare extensions of MyShape

See the listings for: MyCircle.java and MySquare.java.

/*

Three instance variables

double radius
double x
double y
Eight methods:

Six of the methods are simple: getter’s and setter’s for x, y, and radius.
There should also be a getArea method that returns the area (derived from the
radius)
A doesOverlap method. This method should accept a MyCircle as an argument,
and return true if this circle overlaps the circle that the method was
invoked on. [Note: two circles overlap if the sum of their radius' is
greater than the distance between their centers.

*/

public class MyCircle {


private double x;
private double y;
private double radius;

public MyCircle(double xInput, double yInput, double radiusInput) {


setX(xInput);
setY(yInput);
setRadius(radiusInput);
}

public void setX(double value) {


x = value;
}

public double getX() {


return x;
}

public void setY(double value) {


y = value;
}

public double getY() {


return y;
}

public void setRadius(double value) {


radius = value;
}

public double getRadius() {


return radius;
}

public double getArea() {


return Math.PI * Math.pow(radius, 2.0);
}

//if the sum of their radius' is greater than the distance between
their centers.
public boolean doesOverlap(MyCircle otherCircle) {
double sum = otherCircle.radius + radius;
double distance = Math.sqrt(Math.pow((otherCircle.x - x), 2.0)
+ Math.pow((otherCircle.y - y), 2.0) );
return sum > distance;
}
}
package stuff;

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;

//smallest unit of the program. represents just a single square


public class MySquare extends JComponent {
//parameters that might be useful later
int x;
int y;
int width;
int height;
//constructor (notice the super call) this initializes the JComponent
parent class we are extending
public MySquare(int x, int y, int width, int height){
super();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
initializeComonent();
}

//initializer method (c++ habit)


public void initializeComonent()
{
this.setBounds(this.x, this.y, this.width, this.height);
this.setVisible(true);
}

//i override the pain method on this JComponent to just paint a filled
rectangle
// the graphics object is passed to the method through OS calls and
you not need to worry about it.
@Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.RED);
g.fillRect(this.x, this.y, this.width, this.height);
}

As can be seen, MyCircle is defined as extending the class MyShape:

public class MyCircle extends MyShape


this class defines an instance variable radius:

private int radius;

and two methods, a constructor MyCircle and a draw() method.

Looking at the constructor, notice how it first sends a message to invoke it superclass
constructor (i.e. MyShape()), which will set up initial values for the inherited xPos and
yPos variables:

public MyCircle()
{
// call constructor of superclass
super();
radius = 20;
}

and then the MyCircle() constructor goes on to initialise its instance variable radius.

The draw() method draws a circle on the argument g making use of the MyCircle's
instance variable radius:

public void draw(Graphics g)


{
g.drawOval(xPos, yPos, radius, radius);
}

The definition of MySquare follows just the same pattern (See listing MySquare.java).

To compile and execute these classes we do the following:

C:\INT4120\unit07\\inheritance> javac *.java


C:\INT4120\unit07\\inheritance> appletviewer Shapes.html

Notice the use of the wildcard '*' in the use of the command javac. This means that all
files ending in ".java" are compiled — it can save a few commands when working with
a program made up of many classes (all stored in the current directory).

When run the screen should look as follows:


notice the reduced yPos of the square (from the default 50) and the increased xPos of the
circle (from the defalt 50) — this shows the success of the invocation of the inherited
methods through the sending of the setX() and setY() messages in ShapeApplet.java.

Activity 1 — MyCircle and MySquare extensions of MyShape

A class has been defined called MyShape. This class has the following variables and
methods:

class MyShape

Variables Methods

Public int xPos

Public int yPos

Public MyShape()

Public void setX( int newX )

Public void setY( int newY )

See the listing of MyShape.java.

Look at this listing for ShapeApplet.java:

import java.applet.Applet;
import java.awt.*;
public class ShapeApplet extends Applet
{
MyCircle shape1;
MySquare shape2;

public void paint( Graphics g )


{
shape1 = new MyCircle();
shape1.setX(100);
shape1.draw( g );
shape2 = new MySquare();
shape2.setY(20);
shape2.draw( g );
}
}

You need to define 2 new classes, called MyCircle and MyClass that both are direct
subclasses of MyShape . Each class should have a constructor method (setting initial values to
appropriate instance variable such as radius for the circle and sideLenth for the square),
and should also define a draw( Garphics g ) method that makes use of the inherited xPos
and yPos instance variables.

You can use the file Shape.html to load the applet into the appletviewer.

Discussion/Suggested solution to Activity 1

MyCircle and MySquare extensions of MyShape

See the listings for: MyCircle.java and MySquare.java.

As can be seen, MyCircle is defined as extending the class MyShape:

public class MyCircle extends MyShape

this class defines an instance variable radius:

private int radius;

and two methods, a constructor MyCircle and a draw() method.

Looking at the constructor, notice how it first sends a message to invoke it superclass
constructor (i.e. MyShape()), which will set up initial values for the inherited xPos and
yPos variables:

public MyCircle()
{
// call constructor of superclass
super();
radius = 20;
}

and then the MyCircle() constructor goes on to initialise its instance variable radius.

The draw() method draws a circle on the argument g making use of the MyCircle's
instance variable radius:

public void draw(Graphics g)


{
g.drawOval(xPos, yPos, radius, radius);
}

The definition of MySquare follows just the same pattern (See listing MySquare.java).

To compile and execute these classes we do the following:


C:\INT4120\unit07\\inheritance> javac *.java
C:\INT4120\unit07\\inheritance> appletviewer Shapes.html

Notice the use of the wildcard '*' in the use of the command javac. This means that all
files ending in ".java" are compiled — it can save a few commands when working with
a program made up of many classes (all stored in the current directory).

When run the screen should look as follows:

notice the reduced yPos of the square (from the default 50) and the increased xPos of the
circle (from the defalt 50) — this shows the success of the invocation of the inherited
methods through the sending of the setX() and setY() messages in ShapeApplet.java.

Activity 2 — Zener.java listing

/*
Zener.java

This program displays a random Zener card. Zener cards are widely used in
research
in parapsychology (e.g., extra-sensory perception). There are only five
different
card types, called `waves', `cross', `circle', `square' and `star'. Many
experiments hinge on people attempting to guess (or determine by psychic
means!)
which card will be drawn from the pack next.

Anyway, this applet simply displays a random Zener symbol each time it is
started. So the display will be any one of the following images:
(Note that you will only see the images if you are looking at the HTML
version of this

file, Zener.java.html).

The Zener symbols are stored in GIF (image) files, so the `star'

image is in file `zenerStar.gif', and so on. When this applet executes, it

expects to find the image files in the same directory as the java `.class'

file. If not, it will not work.

The real purpose of this program is to demonstrate the use of inheritance. In


this

application we have five different cards (wave, square, etc). Each is


represented

as a separate class. All these classes have something in common: the ability
to

display an image in a GIF file. The difference between classes is the exact
name

of the file. So we create a class called `Card' which contains the


functionality

needed by every card. Then we create classes called `Wave', `Square', etc.,

which implement what is different about each card. It turns out that the

classes that implement the individual classes are very simple; most of the

work is done in the Card class.

Note also that this program is very long for what it does; there are much
simpler

ways to do the same job!

Kevin Boone, August 1999

*/
import java.applet.Applet;

import java.net.URL;

import java.awt.*;

/*

class Zener

This class is an Applet. Whenever it is re-drawn (that is, its `paint()'


operation

called), it creates a new object of one of the Card subclasses, and calls its

`draw()' operation.

*/

public class Zener extends Applet

public void paint (Graphics g)

// Define a variable to store the `Card' object that will be created

Card card;

// To pick a Zener card at random, we will generate a random number

// between 0 and 4, and then use a switch statement to create a

// different Card object according to the number selected

int cardNumber = (int)(Math.random() * 5);

switch (cardNumber)

{
case 0: card = new Waves(); break;

case 1: card = new Cross(); break;

case 2: card = new Circle(); break;

case 3: card = new Square(); break;

default: card = new Star(); break;

// So at this point, `card' will refer to an object of class

// `Waves', `Cross', etc., picked at random

// The Applet class has built-in operations for loading image

// files into memory. The Card object we are defining does not. So we
will

// set an attribute in the card object that specifies the

// current applet. The card will then call the operations in the

// applet that load the image. This is an example of `delegation',


that is,

// using one object to assist the function of another.

card.ownerApplet = this;

// So now we've created the `card' object and told it the applet to
use for

// loading images; not we call its `draw' operation to draw it on the

// screen.

/// QUESTION: why are we passing `g' as a parameter here?

card.draw(g);
}

/*

class Card

This class provides the functionality that is common to all the different
cards

(square, wave, etc).

*/

///QUESTION: why is this class `abstract'?

abstract class Card

/*

The attribute `ownerApplet' will be set to indicate the applet that owns this

card object. This will be used to load the image file into memory before

drawing it on the screen. If we don't do this, we would need to provide

image loading facilities in the Card class, which would be a waste of time

*/

Applet ownerApplet;

/*

drawImageFile

This operation loads the image file specified by the parameter


`imageFilename' and

draws it on the screen. We also pass a `Graphics' object to provide the


drawing facility.

*/

public void drawImageFile (Graphics g, String imageFilename)

// The getImage operation loads an image from a GIF file into an Image
object.

// to do this it needs to know two things: the name of the iamge


file, and

// the location (directory) at which it is stored. The operation

// `getCodeBase' in the Applet class will give the location of the


applet.

// If we assume that the image files are in the same directory, then
we

// can pass the output of getCodeBase directly to getImage. The

// image filename is supplied as a paramter to this operation

Image image = ownerApplet.getImage(ownerApplet.getCodeBase(),


imageFilename);

// The drawImage operation draws the iamge on the screen. It needs to


know the

// applet that will control the drawing process as well

g.drawImage(image, 0, 0, ownerApplet);

/*

draw

This operation draws the card on the screen.

*/

///QUESTION: why is this operation `abstract'?


abstract public void draw(Graphics g);

/*

Classes for indivdual card types.

Notes that these classes are very simple; they have only one operation (draw)
which

calls drawImageFile with the appropriate filename

*/

class Waves extends Card

public void draw (Graphics g)

drawImageFile(g, "zenerWaves.gif");

class Cross extends Card

public void draw (Graphics g)

drawImageFile(g, "zenerCross.gif");

}
class Circle extends Card

public void draw (Graphics g)

drawImageFile(g, "zenerCircle.gif");

class Square extends Card

public void draw (Graphics g)

drawImageFile(g, "zenerSquare.gif");

class Star extends Card

public void draw (Graphics g)

drawImageFile(g, "zenerStar.gif");

}
(1) Study the example program Zener.java and answer the questions in it.

(2) Compile and run the applet with the appletviewer

NOTE: For the applet to work you need to have the GIF image files in the same
directory as the Java source file:

zennerWaves.gif

zennerSquare.gif

zennerCircle.gif

zennerStar.gif

zennerCross.gif
The screen should look similar to the following run:

(3) Make the applet change the displayed shape, i.e. make the screen look these
different ways:

Discussion of notice the reduced yPos of the square (from the default 50) and the
increased xPos of the circle (from the defalt 50) — this shows the success of the
invocation of the inherited methods through the sending of the setX() and setY()
messages in ShapeApplet.java .

Discussion of Activity 2

Zener.java listing

(1) Question in listing


/// QUESTION: why are we passing `g' as a parameter here?
card.draw(g);
The message draw( g ) is requesting that the appropriate draw method be invoked for
the card object, and the g being passed is the current graphics context — i.e. a
reference to the window of the applet in which the image should be drawn. Without this
argument, the draw method invoked would not know where to actually draw its image.
///QUESTION: why is this class `abstract'?
abstract class Card

The class Card has been declared as abstract because it is a class for which we never
want to create an object — we shall only create objects based on the subclasses of
class Card. Making a class abstracts requires the programmer to write subclasses which
are not abstract. The benefit of having an abstract class is that we can create a vathat
can refer to any Card object, i.e. a variable that can refer to any object based on any
subclass of this abstract class.
/// QUESTION ///
// why is this method `abstract'?
abstract public void draw(Graphics g);

A variable that has been declared to refer to objects of a superclass can only have
messages sent to it that are in the protocol (public and protected methods) defined in
the superclass. Therefore, if we wish some variable to be able to refer to different
subclass objects of the Card class, and to invoke polymorphism by the sending of
draw() messages, we have to ensure that the method draw() occurs in the protocol of
the superclass. Hence we declare an abstract method draw() in the abstract class Card.
Each non-abstract subclass will have to define its own implementation of the draw()
method.

(2) As usual we need to run the command line Java compiler with our Java source file:

C:\INT4120\unit07\zener> javac Zener.java


C:\INT4120\unit07\zener> appletviewer Zener.html

The file Zener.html is a simple HTML file to execute the compiled Zener.class.

You will notice when you compile Zener.java that a number of ".class" files appear in
your directory, since there are a number of different classes defined in the one source
file (mainly the subclasses of the Card class).

(3) To get the applet to change the card it is showing we need to make the Zener applet
object invoke its paint() method. We can do this by causing a repaint() message to be
sent — for example by resizing the applet's window, or by covering and then revealing
the applet's window:
Since the selection of the card displayed is random, you may have to reisize the window
two or three times to get a different picture.

Activity 3 – Inheritance issues

Look at the program Inheritance1.java and try to work out what display it will produce.

You can use the following html file to run the applet with the appletviewer:
<BODY>
<APPLET CODE="Inheritance1.class" height=100 width=200></APPLET>
</BODY>

When you think you've figured it out, compile and run the program and check your
answer

Discussion/Suggested solution to Activity 3

Inheritance issues

When executed, the following is displayed:

So what is the sequence of things that happened?


When the html file is executed by the appletviewer, an instance of the Inheritance1 is
created.

<BODY>
<APPLET CODE="Inheritance1.class" height=100 width=200></APPLET>
</BODY>

The steps will be numbered, to help keep track of what is happening to which object.

1) When the new Inheritance1 object is created, is first creates its instance variables

1.1) So a variable s is created, able to refer to String objects. Although for now the s
variable of the Inheritance1 object is null (not referring to any String object):

String s;

1.2) Next the constructor Inheritance1() is executed:

public Inheritance1()
{
s = "aaa";
}

this assigns the variable s to refer to a new String object with the value "aaa"

1.3) Next the Inheritance1 object, since it is an applet object, is sent a repaint()
message (this happens when a new applet object is created). When the Inheritance1
object receives the repaint() message, it executes its paint() method:

public void paint (Graphics g)


{
Inheritance2 i2 = new Inheritance2();
String s = i2.getData();
g.drawString(s, 20, 20);
}

1.3.1) The first statement of the paint() method of the Inheritance1 object declares a
new, local to the method, variable i2. This variable is made to refer to a new
Inheritance2 object:

Inheritance2 i2 = new Inheritance2();

1.3.1.1) A new object of the class Inheriatance2 is created. The class Inheritance2 is
a subclass of the class Inheritance3, and therefore inherits the instance variables and
methods of Inheritance3.

So this new Inheritance2 object inherits the instance variable s, that is initialised to refer
to the String "ccc":

class Inheritance3
{
String s = "ccc";
// rest of class

1.3.1.2) Next the new Inheritance2 object executes its constructor, Inheritance2():

public Inheritance2()
{
super();
s = s + "bbb";}

1.3.1.2.1) The first statement of the Inheritance2() constructor invokes the constructor
of its superclass, in this case the constructor Inheritance3().

super();

The Inheritance3() constructor first invokes its superclass consuctor (i.e. Object() ),
and then assigns a new value to instance variable s. This new value of instance variable
s is a reference to the String "ddd":

public Inheritance3()
{br>super();
s = "ddd";
}

1.3.1.2.2) The second statement of the Inheritance2() constructor makes the instance
variable s refer to the String object created by concatenating is current String "ddd" with
the String "bbb".

s = s + "bbb";

Thus the instance variable s of the Inheritance2 object i2 now refers to the String
"dddbbb".

1.3.2) The second statement of the paint() method of the Inheritance1 object declares
a new, local to the method, variable s. NOTE: Any statements this paint() method will
now refer to this local variable s, not the Inheritance1.s instance variable.

You should avoid, wherever possible, having local variables with the same name as
instance or class variables.

This local variable is made to refer to the same String returned as a reply from sending
the message getData(); to the Inheritance2 object i2:

String s = i2.getData();

This results in the getData() method being invoked for the object i2.

1.3.2.1) The getData() method simple returns a reference to the same String as the
Inheritance2's instance variable s :
public String getData()
{
return s;
}

Since the instance variable s of Inheritance2 object i2 refers to the String "dddbbb", a
reference to this String is returned as a reply by this method.

1.3.3) The third statement of the paint() method of the Inheritance1 object sends a
drawString() message to the Graphics object:

g.drawString(s, 20, 20);

This results in the value of the local variable s (i.e. the reference to the String "dddbbb")
being sent along with the co-ordinates (20, 20) to be drawn on screen.

Thus we see "dddbbb" drawn on screen !

Exercises

Exercise 1 — Inheritance Summary

Complete the following statements that summarise the concepts explored in the
'Inheritance' section of this unit:

The object-oriented feature of ___________ embodies the idea that one thing is
similar to or a ______________ of another thing.

In Java full inheritance is declared with the use of the keyword ________.

A class hierarchy is built up through ____________ and _________.


Inheritance can be direct, via ______ ____________ and _____
_________, or can be indirect between classes separated two or more
levels in the ________.

Discussion of Exercise 1

Inheritance Summary

Suggested completed summary statements are as follows:

The object-oriented feature of inheritance embodies the idea that one


thing is similar to or a specialisation of another thing.
In Java full inheritance is declared with the use of the keyword 'extends'.

A class hierarchy is built up through superclasses and subclasses.


Inheritance can be direct, via direct superclasses and direct subclasses, or
can be indirect between classes separated two or more levels in the
hierarchy.414

Exercise 2 – UML-to- Java

Write Java ‘class’ statements that define in outline the model shown in the diagram
(don’t define any operations)

Discussion of Exercise 2

UML-to-Java

From the UML diagram we can see that class Vehicle is a class that does not explicitly
extend any other class:

class Vehicle
{
}

(so it will implicitly extend the class Object).

The class Car is show by the arrow in the UML diagram to be a subclass of class
Vehicle, so when we define Car we state that it extends the class Vehicle:

class Car extends Vehicle


{
}
Exercise 3 — Java-to-UML A

Draw a UML diagram to show the relationships between classes expressed in the
following Java outline:

class Moveable
{
// methods that define the class Moveable
}
class Shape extends Moveable
{
// methods thdefine the class Shape, that are not
// included in class Moveable
}
class Circle extends Shape
{
// methods that define the class Circle, that are
not
// included in class Moveable or class Shape
}

Discussion of Exercise 3

Java-to-UML A

Class Movable is not explicitly a subclass of any other class (although it must then
implicitly be a subclass of Object). So we just draw a rectangle for Movable.

Class Shape is a subclass of Movable, so we draw an arrow from the rectangle for Shape
to Movable.

Class Circle is a subclass of class Shape, so we draw an arrow from the rectangle for
Circle to Movable .
Exercise 4 — Multiple inheritance

Draw a UML diagram to show the relationships between classes InputReceiver ,


MyButton , Component , Image and Icon as described in the text.

"Any object that can receive input from the user is a subclass of
InputReceiver . Examples might include buttons, menus, window
borders, etc. Any object that can be displayed in a window is a subclass of
Component . The class called MyButton displays a button in a window. This
is a subclass of InputReceiver (because we can activate the button by
pressing the space bar, or clicking the mouse). It is a subclass of
Component because it can be displayed in a window. Icon and Image are
subclasses of Component , but not subclasses of InputReceiver . "

Where is the multiple inheritance in this system? Show it in a UML diagram.

Can the system be reorganised so that it does not exhibit multiple inheritance?

Discussion of Exercise 4

Multiple inheritance
If we make InputReceiver a subclass of Component this would avoid the problem of the
multiple inheritance. However, in reality perhaps not all objects that receive input are
displayable on screen, so this may not replicate the real system.

Exercise 5 — Interfaces summary

Complete the following statements that summarise the concepts explored in the
'Interfaces' section of this unit:

Abstract classes are inherited through the use of the keyword


__________.

A class that has an abstract method must be defined as an ________


_____. Any subclass of an abstract class must _________ all abstract
methods in order to allow objects of that class to be created.

An _________ is conceptually the same as an abstract class whose


methods are all ________.

Discussion of Exercise 5

Interfaces summary

Suggested completed summary statements are as follows:

Abstract classes are inherited through the use of the keyword


'implements'.

A class that has an abstract method must be defined as an abstract class.


Any subclass of an abstract class must implement all abstract methods in
order to allow objects of that class to be created.
An interface is conceptually the same as an abstract class whose methods
are all abstract

Exercise 6 — Java interface as UML

The KeyboardListener interface was defined like this:

interface KeyboardListener
{
void keyPressed();
void keyReleased();
}

Show this interface on a UML diagram -- both ways -- including the operations.

Discussion of Exercise 6

Java interface as UML

or

Note that the second method is neater, but does not allow the operations to be seen
Exercise 7 — Java-to-UML B

Draw a UML diagram to show the relationships between classes expressed in the
following Java outline:

class Component
{
}

interface KeyboardListener
{
void keyPressed();
void keyReleased();
}

class MyButton extends Component implements


KeyboardListener
{
void keyPressed()
{

// instructions describing what


// to do when a key is pressed
}
void keyReleased()
{
// instructions describing
//what to do when a key is released
}
}

Discussion of Exercise 7

ava-to-UML B

We show that MyButton is a subclass of Component in the usual way — with an arrow
from class MyButton to class Component.

We show that MyButton implements the interface KeyboardListener with an arrow from
class MyButton to the rectangle labelled <<interface>> KeyboardListener (to explicitly
show that KeyboardListener is an interface).
Exercise 8 — English-to-UML

The following text describes the inheritance relationships between a small number of
types of animal.
"Reptiles and mammals are types of animal. Snakes and tortoises are types of reptile.
Dogs, cats and platypuses are types of mammal. All reptiles are types of `egg-laying
animal', as are platypuses. Dogs and cats are types of `furry animal'. Tortoises are
types of `animals with shell. "

Write Java 'class' and 'interface' definitions that embody the inheritance relationships
described. For example, the fact that `cats are types of mammal' can be represented
as:

class cat extends mammal


{

You are advised to make a UML diagram showing the inheritance relationships between
these classes. You must avoid multiple inheritance by defining some interfaces.
Discussion of Exercise 8

English-to-UML

// Animals1.java
// This fragment of Java models the following class hierarchy
// Kevin Boone, August 1999
class Animal
{
}
interface Furry
{
}
interface LaysEggs
{
}
interface HasShell
{
}
class Mammal extends Animal
{
}
class Reptile extends Animal implements LaysEggs
{
}
class Dog extends Mammal implements Furry
{
}
class Platypus extends Mammal implements LaysEggs
{
}
class Snake extends Reptile implements LaysEggs
{
}
class Tortoise extends Reptile implements HasShell, LaysEggs
{
}

Exercise 9 — Using abstract methods to generalise the shape applet program

Refer back to Activity 1 — MyCircle and MySquare extensions of MyShape.

We can generalise the MyShape class by providing an abstract draw() method for the
classes MyCircle and MySquare to override.

The advantage of this means that a MyShape variable will be able to refer to an object
that is from any subclass of MyShape, and we can send that variable draw() messages.
The message draw() will be in the protocol for MyShape since it is defined as an
abstract class.
So:

 define an abstract method draw() in the class MyShape


 change your ShapeApplet class to use a single variable shape of type MyShape
 to first have shape refer to a new circle object (as before change its x position and then
make it draw itself)
 then have the shape varaible refer to a new square object (and as before change its y
position and make it draw itself)

Discussion of Exercise 9

Using abstract methods to generalise the shape applet program

So we add an abstract method draw() to MyShape:

// abstract method draw()


abstract void draw( Graphics g );

Notice, we must now make the class MyShape abstract, since any class with one or
more abstract methods must be made an abstract class (since we cannot create
instances of classes with abstract methods). If we try to compile MyShape as a non-
abstract class with an abstract method, we get the following error message:

C:\CMT4120\unit07\ICTerfaces> javac *.java

MyShape.java:3: class MyShape must be declared abstract. It does


not define void draw(java.awt.Graphics) from class MyShape.

public class MyShape

1 error

So our MyShape class now looks as follows:

import java.awt.*;
abstract class MyShape
{
// instance variables
ICT xPos;
ICT yPos;
// constructor
public MyShape()
{
xPos = 50;
yPos = 50;
}
////////
public void setX(ICT newX)
{
if(newX > -1)
xPos = newX;
else
xPos = 0;
}
public void setY(ICT newY)
{
if(newY > -1)
yPos = newY;
else
yPos = 0;
}
// abstract method draw()
abstract void draw( Graphics g );
} // class

We don't need to change either MyCircle or MySquare — both these classes still extend
(subclass) the MyShape class and define their own constructor and draw() methods.

We now need to modify the ShapeApplet class, to use a single variable able to refer to
an object of class MyShape:

MyShape shape;

and we change the rest of the codeso that the shape variable refers to the new
MyCircle and then MySquare objects:

shape = new MyCircle();


shape.setX(100);
shape.draw( g );
shape = new MySquare();
shape.setY(20);
shape.draw( g );

The full listing for our changed ShapeApplet is as follows:

import java.applet.Applet;
import java.awt.*;
public class ShapeApplet extends Applet
{
MyShape shape;
public void paICT( Graphics g )
{
shape = new MyCircle();
shape.setX(100);
shape.draw( g );
shape = new MySquare();
shape.setY(20);
shape.draw( g );
}
}

Review Questions
Review question 1

In `true' multiple inheritance, a subclass may inherit from two base classes that have a
method with the same name. For example, suppose we have a class called `A' and a
class called `B', and both have a method called `test()'. Class `C' is a subclass of both A
and B, and it does not have its own `test()' method. So if we call the method C.test(),
does it call A.test() or B.test()? This confusion is one of the arguments used by the Java
developers for disallowing multiple inheritance in Java. Suppose we have an interface
(not a class) called A and a class called B, and both have a method `test()'. What
happens if class C extends B and implements A, and we call C.test()? How does this
avoid the problem?

Discussion of Review Question 1

If we call C.test(), and C does not have its own `test()' method, then we get A.test(). The
interface B only specifies that there is a test() method, it does not provide any
implementation for it. So in practice there is no ambiguity about which method to call.

Review question 2

To what extent is an interface the same as an abstract class ?

Discussion of Review Question 2

Conceptually an interface is the same as an abstract class whose methods are all
abstract.

For example, the definition:

interface MyInterface
{
void method1();
void method2();
}

is conceptually similar to:

abstract class MyInterface


{
abstract void method1();
abstract void method2();
}
In both cases the class contains the definitions of methods, but no implementation. It is
the job of the subclass to provide implementations for these methods.

Review question 3

What is the purpose of the super keyword?

Discussion of Review Question 3

Super calls a class's base class constructor to be called. Normally when we over-ride a
constructor we want to provide methods that add to the functionality of the base class
constructor. Super provides a mechanism for doing this.

Review question 4

Inheritance can be used to represent the `type of' relationship (e.g., a business
customer is a type of customer).

Can it also be used to represent the `part of' relationship (e.g., wheels are part of a
car?)

Discussion of Review Question 4

There are some similarities between the `part of' and `type of' concepts in object
orientation. For example, in the same way that we say that:

"A business customer is a type of customer, and a customer is a type of


person, therefore a business customer is a type of person''

we can also so:

"A brick is a part of a wall, and a wall is a part of a hour, therefore a brick
is a part of a house''.

However, in a part-of relationship, nothing is inherited. In the `customer' example, a


customer had the same properties as a person (name, address, height, weight, etc). But
in the `brick' example, the brick does not share any properties with a wall, nor does the
wall share any properties with the house.
The issue is a subtle one, but on the whole is not correct to use inheritance to show that
one class is a part of another class. In Java, if I wanted to represent the fact that a
house contains walls I might write:

class House
{
Wall walls[];
}

Review question 5

A keyboard is a type of input device. In Java we could write:


class InputDevice
{
Char getLastCharacterEntered()
{
// this method returns the character last entered by
// the device
}
}
class Keyboard extends InputDevice
{
}

A display screen, however, is a type of output device. So in this case we could write:

class OutputDevice
{
void displayCharacter(char c)
{
// method to display character `c' on the device
}
}
class DisplayScreen extends OutputDevice
{
}

So far, so good. Now consider the touch-screen display. These are commonly used in
information kiosks and museum displays. The touch screen displays information, put it
provides information the computer when the users touches the screen. So is it an input
device or an output device, or both? Ideally we would like to say

class TouchScreen extends InputDevice, OutputDevice


{
}

But we can't do this, because this is multiple inheritance, which is not allowed. To what
extent does the Java `interface' mechanism allow us to represent the notion of a touch
screen as an input device and an output device? Try to write some Java code that
defines a TouchScreen class and its base classes.
Discussion of Review Question 5

One solution might be to make both the base classes interfaces, and implement the
input and output methods in the TouchScreen() class

class InputDevice
{
char getLastCharacterEntered();
}interface OutputDevice
{
void displayCharacter(Char c);
}
class TouchScreen implements InputDevice, OutputDevice
{
void displayCharacter(Char c)
{
// implement the method here
}
char getLastCharacterEntered()
{
// implement the method here
}
}

The problem with this is the use of the interfaces doesn't really achieve very much. If a
TouchScreen displays data very much like an ordinary display screen (and it does), then
it is pointless to re-implement displayCharacter() here when we have probably already
implemented it for the DisplayScreen class. We might be able to get round this by using
the displayCharacter() method in

DisplayScreen like this:


class TouchScreen implements InputDevice, OutputDevice
{
void displayCharacter(Char c)
{
DisplayScreen.displayCharacter(c);
// do things here that are specific to the touch screen, and not
// included in DisplayScreen...
}
char getLastCharacterEntered()
{
// implement the method here
}
}

This process is called delegation. It has been argued by some Java authorities that the
use of delegation can totally obviate the need for multiple inheritance. This remains a
controversial statement.

Discussion Topics

Discussion Topic 1 — The 'diamond of death' class model


It is easy to make a case for disallowing multiple inheritance by considering the so-
called `diamond of death' class model. This is a class structure as shown below:

Here D is a subclass of B and C (multiple inheritance), while B and C are both


subclasses of A. It might seem at first sight that this structure is unusual, but in practice
it can occur quite frequently.

What real-world structures may lead to `diamond of death' class structures?

What are the problems with this structure?

Contribution for Discussion Topic 1

The 'diamond of death' class model

One example of real-world dimond of death situations is where people, or objects, have
multiple roles or functions. For example a company might have a gerenal class
Employee, and subclasses FullTimeEmployee and PartTimeEmployee (each with
different methods for tax, salary, holiday calculations and hiring-firing procedures etc.).
There mabe job sub-classes of each class, e.g. Manager, OfficeWorker, FactoryWorker.
There may be specific jobs, such as Machinist, subclass of FactoryWorker. So we could
have Machinish having 2 direct superclasses: FactoryWorker and FullTimeEmployee,
also this factory worker might also do extra work part time, and so also be a subclass of
PartTimeEmployee.
Another real-world example could be for a factory that makes kitchen utensils. Consider
a superclass Utensil (or Product) with subclasses BottleOpener and Corkscrew. Now
consider an object that is a combined bottle opener and corkscrew. These classes may
define operations such as stresses and strains, manufactory operations that can be
applied to them etc.

The problem with the structure is ambiguity of inheritance. Consider a method M()
defined in class A. Let us assume that this method is overriden in class C, but not in
class B. Therefore class B objects use the inherited method M() from class A. If class D
does not override method M(), should a class D object inherit method M() from its
superclass B (and therefore class A), or should class D inherit the overridden method
from its superclass C? This is a problem of multiple-inheritance.

Discussion Topic 2 — Multiple inheritance

Considering these issues, do you think multiple inheritance is a good thing or a bad
thing in programming?

You might like to look into some of the previous discussion on this subject. Try doing a
Web search for 'multiple inheritance'

Contribution for Discussion Topic 2

Multiple inheritance

Some advantages of multiple inheritance are:

 elegant class hierarchies


 reduction in coding

Some disadvantages of multiple inheritance are:

 more complex class hierarchies (harder to create, debug, understand and work
with)
 issues of resolving inheritance from different superclasses
 difficulties in converting multiple inheritance object-oriented programs / designs
into languages that only support single inheritance (no problems the other way
around)

Reflection on Learning Experience


In your Learning Journal write up your experience of your learning on this unit. Say what
you thought was good or bad, what you had difficulty understanding, and how you
resolved your problems.

Additional Content

Additional reading

 'Inheritance' section in Sun's on-line Java tutorial


 'Interfaces' section in Sun's on-line Java tutorial

Additional Exercises

Extension exercises

Complete exercises from Chapter 9 Deitel and Deitel pp 450-454

Optional reflection topic

Optional reflection topic – 'mix-in' classes

A `mix-in' class is one that provides a small amount of functionality. Mix-ins are intended
to simplify implementation; a mix-in class rarely models a real-world entity.

Here is an example. It may be useful to allow objects to be able to save their states to a
disk file. For example, when I start my word processor, its appearance is very much as
it was when I last used it (position on screen, layout of buttons, etc). Clearly the objects
that model the screen appearance are able to `remember' their variables from the last
use of the program. The programmer may get this feature by defining a class called,
say, CanSaveToDisk , and making all other classes subclasses of CanSaveToDisk. This is
an example of a mix-in class; it provides a small, well-defined piece of program
functionality.

Java does not readily support mix-in programming.

Why?

Can anything be done about this?

Reflect back to the 'dimond of death' and problems of multiple inheritance — the use of
`mix-in' programming presents a particular problem in this regard. Why?
End of Unit Review

Before proceeding to the next unit you should work through this set of review questions.
When you have completed the questions you will be able to obtain the answers for
future reference.

Your performance with these questions will not affect your grade for the module, but
may be monitored so that your tutor can be alerted if you are having difficulty.

Please contact your tutor if you feel you have not done as well as you expected.

Now complete the end of unit review questions online.

Das könnte Ihnen auch gefallen