Inheritance
In the world of Java every child is at least as good as his/her parent, unless it messes something up.
Object oriented languages such as Java provide a mechanism for reusing code known as inheritance.
- Inheritance allows you to take an existing class and specialize it.
- The original class is called the super, base, or parent class (these terms are used interchangeably).
- The class that specializes the base class is called the sub, derived, or child class (these terms are used interchangeably).
- Inheritance is useful because it allows us to:
- reuse existing code without modifying the original code
- create a family of related classes
- treat objects from all the related classes in the same way
Object Class
- All classes in Java are descendants of the
Object
class. - The
Object
class defines a number of methods, e.g.,equals()
which can be used to see if two objects have the same value.toString()
which returns a String representation of the object.
- Because every class is a descendant of the
Object
class, all other classes inherit these methods, i.e., it is possible to calltoString()
on an object from a class you wrote even if you didn't implement thetoString()
method.
Suppose we have the following class defined:
public class A {
}
Even though the class has no methods explicitly implemented, we can still do the following:
A instance = new A();
System.out.println(instance.toString());
Running this code would produce something like this:
packageName.A@82ba41
- Calling
toString()
on the instance executes the implementation oftoString()
found in theObject
class. - The string returned specifies the package name and class name, separated by a period, and then the memory address (in hexadecimal) where the object is stored.
- Essentially, the
Object
class provides generic behavior for thetoString()
method... no matter what kind of object we have, we can always describe it with a string containing the package name, class name, and memory location where it is stored. - When we create a specialized class (one that inherits from
Object
), it may make sense to rewrite the functionality oftoString()
that was inherited fromObject
. - We can do this be overriding the definition of the
toString()
method like this:
public class A {
public String toString() {
return "This is an object from the silliest class I have ever seen";
}
}
Running the code below results in This is an object from the silliest class I have ever seen.
A instance = new A();
System.out.println(instance.toString());
- Calling
toString()
now executes the specialized version of thetoString()
method that has been customized for the subclass.
Class Declaration Syntax
- Java assumes that we are inheriting from the
Object
class unless told otherwise. - The extends keyword is used explicitly identify a superclass.
- Consider the following Shape class:
public class Shape {
private Color color;
private double xCoord;
private double yCoord;
public Shape() {
color = Color.WHITE;
xCoord = 0.0;
yCoord = 0.0;
System.out.println("Shape: constructor");
}
public void draw() {
System.out.println("Shape: draw");
}
public void erase() {
System.out.println("Shape: erase");
}
public void move() {
xCoord += 5.0;
yCoord += 5.0;
System.out.println("Shape: move");
}
public void zoom(double magnification) {
System.out.println("Shape: zoom");
}
public Color getColor() {
System.out.println("Shape: getColor");
return color;
}
public void setColor(Color color) {
this.color = color;
System.out.println("Shape: setColor");
}
}
- We can inherit from
Shape
to create a class that describes a particular type of shape. For example,
public class Circle extends Shape {
private double radius;
public Circle() {
super();
radius = 0.0;
System.out.println("Circle: constructor");
}
public void draw() {
System.out.println("Circle: draw");
}
public void erase() {
super.erase();
System.out.println("Circle: erase");
}
public void zoom(double magnification) {
radius *= magnification;
System.out.println("Circle: zoom");
}
public void setRadius(double radius) {
this.radius = radius;
System.out.println("Circle: setRadius");
}
public double getRadius() {
System.out.println("Circle: getRadius");
return radius;
}
}
- By extending
Shape
, ourCircle
class inherits the three fields from. - Because
color
,xCoord
, andyCoord
fields are declare as private, they are not visible in theCircle
class, even though they exist as part of aCircle
object. - Notice that the
Circle
constructor calls theShape
constructor by callingsuper()
. If a superclass has multiple constructors, we can specify the desired constructor by passing the correct parameters tosuper()
. - The
Circle
class does not implement thegetColor()
andsetColor()
methods. The implementations provided by theShape
class are inherited, i.e., used, by theCircle
class. - The
Circle
class does implement its own versions ofdraw()
,erase()
, andzoom()
. Rewriting the functionality of a superclass's method is called overriding.draw()
andzoom()
provide a completely new implementation for theCircle
classerase()
makes use of theShape
'serase()
implementation by callingsuper.erase()
and then adds some additional functionality.
getRadius()
andsetRadius()
are additional methods that are only available to theCircle
class.
Can you figure out what the following program will display?
public static void main(String[] args) {
Shape shape = new Shape();
Circle circle = new Circle();
shape.move();
circle.move();
shape.draw();
circle.draw();
shape.zoom();
circle.zoom();
shape.erase();
circle.erase();
circle.getRadius();
}
Note:
shape.getRadius()
would produce a compiler error becausegetRadius()
is not defined in theShape
class.- A reference to a
Shape
may point to aCircle
object since a circle can do everything that a shape can do. - A reference to a
Circle
may not point to aShape
object since a circle can do more than a shape (likesetRadius()
).
The is-a Lingo
- Often inheritance is discussed using is-a terminology.
- The terminology is used to help identify when it is appropriate to use inheritance in object oriented design.
- When designed correctly, a subclass object is a superclass object.
- In our previous example, it makes sense to say that a
Circle
is aShape
. - Using this terminology may clarify the notes above:
- A reference to a
Shape
may point to aCircle
object since a circle is a shape. - A reference to a
Circle
may not point to aShape
since a shape isn't necessarily a circle.
- A reference to a
Visibility Modifiers
- We've already discussed the
private
andpublic
visibility modifiers. - Attributes (fields or methods) that are declared
public
are accessible to anyone. - Attributes that are declared
private
are only accessible to the class. - Attributes that are declared
protected
are accessible to the class and any descendent class.