Title: Chapter 13: Extending Classes
1Chapter 13 Extending Classes
- Object-oriented languages differ from other
procedural languages because OOPLs offer
inheritance - This is done by extending a class
- Extending a class creates a subclass where
everything in the parent class is available to
the subclass - This is inheritance
- your subclass inherits items from your parent
class - You can control what gets inherited, but
generally, most of or all of the parent class
will be inherited - The advantage of inheritance is in class reuse
- Why reinvent the code already written in a class
when you have to do something a little different? - Instead, extend the class to include the new
features desired - We have already seen this to a small extent in
this course - Exceptions, and you may have also extended JFrame
or Applet
2What Does Inheritance Mean?
- Inheritance is a process whereby a new class has
access to (or copies) the items defined in a
previous class - Data members
- Methods including the constructor
- Thus, a subclass is truly an extension to a
previously defined parent class (known as the
superclass) - the subclass contains everything that the parent
class had, but extends it - you can control what is inherited so that you
can limit what the subclass begins with
3Some OOP Terminology
- Protected a visibility modifier used to allow
inheritance for data members or methods but to
restrict these elements to being private
otherwise - Class Hierarchy the relationship of classes
viewed pictorially - Polymorphism the treatment of an object that
can be the declared class or any subclass of the
declared class
- Superclass the parent class
- Subclass the child class (also called a derived
or extended class) - Extend the Java keyword to create a subclass
- Inheritance using (obtaining) methods and data
members of another class by extending the class
Historical notes OOP and inheritance came out
of Artificial Intelligence research of the
1970s The first OOP was Smalltalk, released
around 1980
4Extending a Class
- Extending a class is done by adding extends
classname to the end of the class being defined
where classname is the superclass - Example public class Foobar extends Foo
- The class Foobar now contains everything that Foo
had, but we can add to it by defining new data
instances and new methods - Members defined in Foobar are not available to
Foo, but anything defined in Foo is available to
Foobar - If Foo defines methods m1, m2 and m3, and we
declare x to be a Foobar, then x.m1( ) x.m2( )
and x.m3( ) are all legal
5Example Class Hierarchy
- Here we have a hierarchy of people in the world
- We might choose to implement them in different
classes so that each class can be specialized
based on the type(s) of information and processes
utilized when reasoning about that particular
class - How does an undergraduate differ from a grad
student? - How does a worker differ from a student?
- How does a manager differ from a drone?
- We can represent these differences
- Notice that the hierarchy might not properly
reflect reality what if you are a student and a
worker? - This requires multiple inheritance, something
that is not available in Java - We will consider multiple inheritance later in
this chapter
6Why is Inheritance Useful?
- One of the most convincing examples of why we
should use OOP and inheritance is in developing
GUIs - Smalltalk was used to create the first GUI-based
windowing environment - Create a window class
- It contains data instances of size, location,
contents, and methods to move, resize, shrink,
etc - Now create specific window classes that extend
window such as a text editor, a CPU usage
monitor, a dialog box, a game, etc - Each of these inherit the basic windows features
the drop-down menu, the commands to move,
resize, etc but they all specialize their class
to have more features and abilities - This is one example, but it clearly demonstrates
that any defined class might not be complete and
inheritance provides a mechanism for another
programmer to extend it
7OOP Keywords in JavaProtected and Final
- protected is a visibility modifier, introduced
previously to allow a class to share its members
with another class defined in the same package - But protected is also used to control inheritance
- If a member of a class
- is public, it is available to everyone
- is private, it is available to only other items
of the class - is protected, it is available only to other items
of the class, or to subclasses, or classes
defined in the same package - final has been used as a modifier so that a
variable cannot be changed making the variable a
constant - In a class definition, final is used so that the
class cannot have subclasses a final class is
at the bottom of the class hierarchy
8Overriding Methods
- Note that even if we inherit everything from the
parent class, we dont have to use everything
from the parent class - If the parent class has a method that we want to
change to be more specific to the child class, we
can go ahead and redefine it in the child class
as a new version of the method - The new method overrides the parents method,
thus while it is still inherited, it is not used - We will do this, for instance, to override a
parent class constructor - If our child class has a data instance not in the
parent class, then the parents constructor will
not initialize this data instance, so we define a
new constructor - We similar define methods to override the
parents methods as needed
9Super
- One additional keyword to note is super
- We have already used this when trying to clone a
class by calling the class parent class, which
should be Object, and invoking its clone method - super.clone( ) call this class parent class
clone method - super will be used when we want to call some
method of the parent class that has been
overridden by the child class - Why would we have call the parents method if we
have overridden it? - Because the parents method might be able to do
part of or most of the work for us, and the new
method might only have to add a little to the
process - For instance, if a child class has an added data
instance, count, which we want to add 1 to in
some method, then we might do the following
public void somemethod( ) super.somemethod(
) count
the parent class method does most of the work,
here we call it and then add 1 to count
10Example Clocks
- Now that we have explored what it means to extend
a class and inherit a from a parent class, lets
take a look at an example - Here we will create a clock class and then extend
it for more particular types of clocks - Although the book presents this example, the
author omits some necessary details
- Start with a Clock class that contains a data
member of the current time (stored as a Time
object) and has methods to construct a Clock,
advance the clock by some minutes, get the hour
and minutes, return if it is morning (boolean),
and set the time to a new time - Extend the class to create a CuckooClock class by
adding an isCuckooing method (true if the time is
exactly on the hour) - Extend the Clock class again to create a 24 hour
clock (using military time) which will require
overriding the getHour method
11The Clock Class
public class Clock protected Time
theTime // made a protected data instance so
that it can be inherited public Clock( )
// instruction(s) to set theTime to
be the time based on the system clock
public advance(int minutes) //
instructions to advance the clock by minutes
public int getHour( )
// instructions to access the hour portion of
theTime and return it public int
getMinutes( ) // instructions to
access the minutes portion of theTime and return
it public boolean isMorning( )
// instructions to determine if am or pm,
returning true or false public void
setTime(int hour, int minute, boolean morning)
// instructions to set theTime
appropriately
Details are omitted for space reasons
12CuckooClock and Clock24 classes
public class CuckooClock extends Clock
public boolean isCuckooing( ) return
(getMinute( ) 0)
Extending the Clock class to create a
CuckooClock merely requires adding 1 method
(note no new data instances) The
Clock24 class again requires no new data
instances but does require new methods for
getHours, setTime and isMorning since hours
will now range from 0-23 rather than 1-12.
Notice that we do not reinvent the code to
obtain the hours from 1-12, but instead call
upon Clocks getHours method to help us in the
new getHours method
public class Clock24 extends Clock
public int getHours( ) int
ordinaryHours super.getHours(
) if(ordinaryHours 12) if(isMorning(
)) return 0 else return 12 else
if(isMorning( )) return ordinaryHours else
return (ordinaryHours 12)
13Using the Clock classes
- At compile time, c is declared to be a Clock but
it can be instantiated as a Clock or a Clock24
(or a CuckooClock) - c.setTime() will call Clocks setTime because it
is the only version that has this method no
matter what type of Clock c is - But, which version of getHours( ) should be
invoked? - This is decided at run-time, not compile-time
- The idea that the variable c might either be a
Clock or a Clock24 is known as polymorphism - c is known as a polymorphic variable, it can
change types - Recall that in Java, the type of any variable is
set at compile time and cannot change - But, polymorphic variables are treated
differently in that they can change types as long
as they remain a type related to (descendant of)
the declared type
- Consider the code below which declares c to be a
Clock what kind of clock can it be?
Clock c if(userAnswer M) c new
Clock24( ) else c new Clock( )
c.setTime(hours, minutes, morning) int h
c.getHours( ) System.out.println(The hour is
h)
14Widening and Narrowing a Clock
- We saw in the previous example that a variable of
type Clock can point to an object of type Clock24 - If we declare a variable to be one type of
object, it can be instantiated as (or take on the
value of) a child of that object class - Thus, c (from the previous slide) can point to a
Clock or a Clock24 (or a CuckooClock)
Following the above rule, which of
these assignments is legal? we are taking a
Clock object and assigning a wider classed
object to point at it , this is a widening
assignment which is permissible Here, however,
we are narrowing the object pointed to by c to
be pointed at by a Clock24 pointer, this
narrowing is illegal unless we add an explicit
cast
Clock c new Clock( ) Clock24 c2 new
Clock24( ) c c2 c2 c c2 (Clock24) c
15Comparing Clocks
- Polymorphism and the ability to change the type
of object that a pointer is pointing too gives a
lot of flexibility - Consider code to the right
- It takes two Clock arguments and determines if
the first is set to an earlier time than the
second - Called with earlier(c, c2)
- c is a Clock
- c2 is a Clock24
- but it works fine
public boolean earlier(Clock c1, Clock c2)
if(c1.isMorning( ) !c2.isMorning( ))
return true else if(!c1.isMorning( )
c2.isMorning( )) return false else
if((c1.getHour( ) 12) c2.getHour( ) !
12)) return true else if(c1.getHour( ) !
12)) c2.getHour( ) 12)) return false
else if(c1.getHour( )
return true else if(c2.getHour( )
c1.getHour( )) return false else
if(c1.getMinute( )
true else return false
16Subclass Constructor
- Lets focus on how we construct a subclass
- If a class data members are initialized in the
class constructor and these members are all
inherited and an extended class defines no
additional data members - Then use the parents constructor
- Note you dont have to provide the constructor
- the subclasss constructor will default to super(
) if nothing is specified
- However, if the extended class has new data
members - then the child class should have its own
constructor - What if the parent class has data instances that
are not inheritable? (I.e. they are private
instead of protected) - Then you may not be able to use the parents
constructor - if the constructor initializes private data
instances that the child does not inherit, it
will result in a compiler error!
public SubClassName( ) super( ) //
call parent class constructor // initialize
data instances unique // to this class
here
public SubClassName( ) super( ) //
call parent class constructor
17Something to Remember
- You might think
- why extend a class, why not just rewrite the
class? - In practice, you may not have access to the
source code - Without the source code, you cannot rewrite the
class - However you are still able to extend the class
- Consider giving someone a .class version of one
of your classes - They want to enhance your class to add more
methods - They must use inheritance
- Now, we have a tool that allows us to build upon
other peoples software by extending their
classes - Good documentation will help the next programmer
extend your class without the comments, the
programmer may not know exactly how to use some
of the inherited methods! - Also remember that you have to change your
private data instances (and private methods) to
be protected instead
18Another Example
- The book next provides a more detailed example of
extending a parent class - In this case, the class parent class is called
Organism and has children of Animal and Plant - Animal has children of Herbivore and Carnivore
- Herbivore has a child class Elephant
- Carnivore has children of BirdOfPrey and Tiger
- This example provides more details than the Clock
example - The book provides details of 4 of the classes,
Organism, Animal, Herbivore and Carnivore - How might Elephant differ from Herbivore?
- For instance, would Elephant include a peanuts
needed data instance? - How might Bird of Prey and Tiger differ from
Carnivore? - Would Bird of Prey include a calories burned by
flying data instance? - How might Plant differ from Organism?
19Animal Class Hierarchy
- The hierarchy to the left reflects the books
Organism class and its subclasses - Organism has two data instances while Animal and
Plant add two more data instances - Animal, Herbivore and Carnivore have extra
methods - Bird of Prey has an extra data instance
- In this example, everything in a super class is
inherited in the subclass but some methods are
overridden - See the example on pages 628 642 for more
details
20Using Inheritance to Build ADTs
- The book offers another example of using a linked
list ADT to create a Stack ADT - The linked list has a current pointer that points
to the current item of interest in the list, they
use this to implement the Stack - In the child class, which extends the linked list
class, add the methods for push and pop - Push call the method to reset the current
pointer to equal head (this method is called
start), and then call the method addAfter( ) - Pop if size do start( ), getCurrent( ) (returns the value of
the current item, which is the first item after
start), and then removeCurrent( ) - This approach is kind of ridiculous, the Stack
ADT is easy enough to build, but it demonstrates
how you might be able to take a class defined for
a specific purpose and extend it for a very
different application
21Multiple Inheritance
- As mentioned earlier, a subclass might actually
be related to multiple parent classes - This creates a tangled class hierarchy
- sometimes referred to as a graph
- Java, unfortunately (or fortunately?) does not
permit a class to inherit from multiple classes - Some OOPs do permit multiple inheritance
- Such as C and Common Lisp
- but most languages do not permit this, like Ada
and Smalltalk - Multiple inheritance greatly complicates matters
because you have to be very careful in
controlling what is inherited - Without multiple inheritance, your class can only
inherit from its super class making some
applications more difficult to implement - Example An undergraduate student who is also an
employee we want to determine the persons
style of living (e.g., lavish, poor, etc) - An undergraduate student would have one style, an
employee another - Which should the combined student/employee have?
22Interfaces A Form of Multiple Inheritance
- We can extend one class and also implement others
to inherit from both the class being extended and
the abstract classes being implemented - Consider a class that defines a Frame with
buttons but does not do anything specific - We extend the class to be a particular GUI, and
implement ActionListener thus, our class is
inheriting from two classes, the Frame class and
ActionListener - This is a week form of multiple inheritance,
unlike what is available in C, but also a safer
and easier form of multiple inheritance
- Earlier in the semester we looked at the
interface, which allows us to implement an
abstract class within a class that we are
defining - For instance, we may have created a GUI class
that implemented ActionListener or a Bag that
implemented Cloneable - This is a form of multiple inheritance
- Our new class is inheriting the properties of the
abstract class even though we have to implement
the details
23Another Example
- To wrap up this material, lets consider another
example - Lets create a class hierarchy of geometric shapes
- Each class will have the data instances necessary
to reason over that particular shape and each
class will have methods to access and reason over
that shape - All shapes will need constructors and all shapes
will have a toString method - 2-D shapes will have areas and perimeters while
3-D shapes will have volumes - Different shaped objects will have different
formulas to compute these values - Rather than providing classes for all possible
shapes, we will limit this example to some of the
basic shapes square, cube, circle, sphere,
cylinder
24The Shape Hierarchy
Here is one way to organize our classes.
Is it logical? We could instead arrange the
classes under Shape to be square- based and
circular, and then place under square-based
the classes square and cube, and under
circular the classes circle, sphere and
cylinder
Even better might be to have cube extend square
and have sphere and cylinder extend circle why
might this make more sense?
25Defining Shapes
public class Shape2D extends Shape
protected double area protected double
perimeter public Shape2D(double iSize,
double iArea, double iPerimeter)
super(iSize) area iArea perimeter
iPerimeter public String
toString( ) return 2D Shape has size
size area area perimeter
perimeter
public class Shape protected double
size public Shape(double iSize)
size iSize public
String toString( ) return Shape
has size size
what would Shape3D look like?
26Defining Shape2D Subclasses
public class Square extends Shape2D
public Square(double length) size
length area getArea( ) perimeter
getPerimeter( ) protected double
getArea( ) return size size
protected double getPerimeter( )
return size 4
public class Circle extends Shape2D
public Circle(double length) size
length area getArea( ) perimeter
getCircumference( )
protected double getArea( ) return
length length pi
protected double getArea( ) return 2
length pi
27Defining Shape3D Classes
- In our original hierarchy of Shapes, it was
commented that the organization might not make
the most sense - Should Shape3D inherit from Shape or would it
make more sense to let Shape3D inherit from
Shape2D? - Shape2D offers a Square and a Circle
- Shape3D will have a Cube and a Sphere
- Cube can inherit area from Square and then use it
to compute volume - Thus, Cube extends Square and adds a data
instances called volume, the constructor calls
Squares constructor and then sets volume to the
value obtained by calling a new method getVolume,
and the toString method is modified - Sphere and Cylinder can similarly inherit from
Circle, as shown on the next slide
28Defining 3D Shapes
If we had made our 3D shapes subclasses of our 2D
shapes, defining them would be easier Assume
that Sphere and Cylinder are children of Circle,
then their definitions can be as shown below
public class Cylinder extends Circle
private double volume private double
height public Sphere(double size, double
iHeight) super( ) height
iHeight volume getVolume( )
private double getVolume( )
return super.getVolume( ) height
private String toString( )
return super.toString( ) height height
volume volume
public class Sphere extends Circle
private double volume public
Sphere(double size) super( )
volume getVolume( )
private double getVolume( ) return
4 length length length pi / 3
private String toString( )
return super.toString( ) volume
volume
29Finally
- You will revisit the idea of OOP and inheritance
throughout your CS career - In 364 (Data Structures and Algorithms), you will
do similar things in C as to what you have seen
here - CSC 444 Object-oriented software development
obviously covers OOP - CSC 425 Artificial Intelligence inheritance
plays a central role in default reasoning and
AI pioneered many of the concepts now found in
OOP - CSC 440 Software Development will require large
software implementations which can be simplified
through OOP - To end our discussion on inheritance and
extending classes, we will take a look at some
Applet examples - Examples will be made available on the
instructors web site