Inheritance Part II
- Contents
- The
Object
Class - Polymorphism
- Polymorphism and Dynamic Binding
- Abstract Classes
- Abstract Methods
- Interface
- Fields in Interface
- Implementing Multiple Interfaces
- Polymorphism with Interfaces
The Object
Class
All Java classes are directly or indirectly derived from a class named
Object
.Object
is in thejava.lang
package.Any class that does not specify the
extends
keyword is automatically derived from theObject
class.- Refer to the
Shape
class in the previous example.
- Refer to the
Ultimately, every class is derived from the
Object
class.Because every class is directly or indirectly derived from the
Object
class:Every class inherits the
Object
class’s members.public String toString(); public boolean equals(Object other); public int hashCode();
In the
Object
class, thetoString
method returns a string containing the object’s class name and a hash of its memory address.- Refer to Chapter 9 lecture notes for
toString
- Refer to Chapter 9 lecture notes for
In the
Object
class, theequals
method accepts the address of an object as its argument and returns true if it is the same as the calling object’s address.- Refer to Chapter 9 lecture notes for
equals
- Refer to Chapter 9 lecture notes for
Book example:
Example code:
public class Program { public static void main(final String[] args) { final Shape myShape1 = new Shape("Circle", "Red"); System.out.println("Shape 1's toString method returns: " + myShape1); final Shape myShape2 = new Shape("Circle", "Red"); System.out.println("Shape 2's toString method returns: " + myShape2); System.out.println("Are two shapes 'equal': " + myShape1.equals(myShape2)); } } class Shape { private final String name; private final String color; public Shape(final String name, final String color) { this.name = name; this.color = color; } }
Polymorphism
A reference variable can reference objects of classes that are derived from the variable’s class.
Refer to the
Shape
class hierarchy in the Chain of Inheritance section.Shape myShape;
We can use the
myShape
variable to reference aShape
object.myShape = new Shape("Shape Name", "Red");
The
Shape
class is the superclass for theRectangle
class, so aRectangle
is a type ofShape
.A variable of type
Shape
can be used to reference aRectangle
object.Shape myShape = new Rectangle(8, 10, "Red");
The previous statement creates a
Rectangle
object that stores the object’s address in themyShape
variable.This is an example of polymorphism.
The term polymorphism means the ability to take many forms.
In Java, a reference variable is polymorphic because it can reference objects of types different from its own, as long as those types are subclasses of its type.
Other legal polymorphic references from the example in the Chain of Inheritance section:
Shape myShape = new Rectangle(8, 10, "Red"); Shape myShape = new Square(9, "Blue"); Rectangle myShape = new Square(9, "Blue");
Example code:
- Refer to the example in the Chain of Inheritance section.
Polymorphism and Dynamic Binding
If an object of a subclass has overridden a method in its superclass, and the its variable makes a call to that method, the subclasses’s version of the method will return.
Refer to the example in the Chain of Inheritance section.
-
Shape myShape = new Rectangle(8, 10, "Red"); myShape.show(); Shape myShape = new Square(9, "Blue"); myShape.show();
Java performs dynamic binding, also known as late binding, when a variable contains a polymorphic reference.
The Java Virtual Machine determines at runtime which method to call, depending on the type of object that the variable references.
It is the object’s type, rather than the reference type, that determines which method is called.
Book example:
You cannot assign a superclass object to a subclass reference variable without casting.
Rectangle rect1 = new Rectangle(5, 5, "Red"); Shape shape = rect1; Rectangle rect2 = (Rectangle)shape;
This is known as downcasting and can generate a runtime error,
java.lang.ClassCastException
, if the conversion cannot be made.Example code:
- Refer to the example in the Chain of Inheritance section.
Abstract Classes
An abstract class cannot be instantiated, but other classes can be derived from it.
An abstract class serves as a superclass for other classes.
The abstract class represents the generic or abstract form of all the classes that are derived from it.
A class becomes abstract when you place the
abstract
key word in the class definition.public abstract class ClassName { : }
Abstract Methods
An abstract method has no body and must be overridden in a subclass.
An abstract method has only a header followed by a semicolon.
AccessSpecifier abstract ReturnType MethodName(parameterList);
Book example:
Notice that the keyword,
abstract
, appears in the header and that the header ends with a semicolon.public abstract void show();
Any class that contains an abstract method must be declared
abstract
.If a concrete subclass fails to override an abstract method, a compiler error will result.
Abstract methods are used to ensure that a concrete subclass overrides a method.
Example code:
public class Program { public static void main(final String[] args) { Shape myShape = new Square(8); myShape.show(); } } abstract class Shape { private String name; public Shape(final String name) { this.name = name; } public abstract void show(); } abstract class Rectangle extends Shape { private int length; private int width; public Rectangle(final int length, final int width) { super("Rectangle"); this.length = length; this.width = width; } } class Square extends Rectangle { private int edge; public Square(final int edge) { super(edge, edge); this.edge = edge; } @Override public void show() { System.out.println("A square with edge length " + this.edge); } }
Interface
An interface is similar to an abstract class that has all abstract methods and no instance fields.
- It cannot be instantiated.
- All of the methods listed in an interface must be written elsewhere.
The purpose of an interface is to specify behavior for other classes.
An interface looks similar to a class, except
- The keyword
interface
is used instead of the keywordclass
. - The methods that are specified in an interface have no bodies, only headers. And they are terminated by semicolons.
- The keyword
The general format of an interface definition:
interface InterfaceName { : }
All methods specified by an interface are
public
by default.If a class implements an interface, it uses the
implements
keyword in the class header.class ClassName extends SuperClassName implements InterfaceName { : }
A class can implement one or more interfaces.
class ClassName implements InterfaceName1, InterfaceName2 { : }
Book example:
Example code:
public class Program { public static void main(final String[] args) { Shape myShape; myShape = new Rectangle(8, 10); myShape.show(); myShape = new Square(5); myShape.show(); } } interface Shape { // Note this is public by default. void show(); } class Rectangle implements Shape { private final int length; private final int width; public Rectangle(final int length, final int width) { this.length = length; this.width = width; } @Override public void show() { System.out.println("A rectangle with length " + this.length + " and width " + this.width); } } class Square implements Shape { private final int edge; public Square(final int edge) { this.edge = edge; } @Override public void show() { System.out.println("A square with edge length " + this.edge); } }
Fields in Interfaces
An interface can contain field declarations.
- All fields in an interface are treated as
final
andstatic
. Because they automatically become
final
, you must provide a initialization value.public interface InterfaceName { int AFIELD = 1; : }
In this interface,
AFIELD
is afinal static int
variable.Any class that implements this interface has access to this variable.
- All fields in an interface are treated as
Example code:
public class Program { public static void main(final String[] args) { Shape myShape; myShape = new Rectangle(8, 10, Shape.Red.Rust); myShape.show(); myShape = new RaspberrySquare(9); myShape.show(); } } interface Shape { enum Red { Amaranth, Auburn, Burgundy, Cardinal, Carmine, Cerise, Chestnut, Crimson, DarkRed, Cremson, FireBrick, Flame, Folly, Fuchsia, Lust, Magenta, Raspberry, Red, RedViolet, Redwood, Rose, Rosewood, Ruby, Rust, Scarlet, TerraCotta, TuscanRed, Vermilion, Wine } public void show(); } class Rectangle implements Shape { private final int length; private final int width; private final Red color; public Rectangle(final int length, final int width, final Red color) { this.length = length; this.width = width; this.color = color; } @Override public void show() { System.out.println("A rectangle with length " + this.length + " and width " + this.width + " and color " + this.color); } } class RaspberrySquare implements Shape { private final int edge; private final Red color; public RaspberrySquare(final int edge) { this.edge = edge; this.color = Red.Raspberry; } @Override public void show() { System.out.println("A square with edge length " + this.edge + " and color " + this.color); } }
Implementing Multiple Interfaces
In Java, a class may extend only one superclass, which may be concrete or abstract.
Java allows a class to implement multiple interfaces.
When a class implements multiple interfaces it must provide the methods specified by all of them.
To specify multiple interfaces in a class definition, list the names of the interfaces, separated by commas, after the
implements
keyword.Example:
class MyClass implements Interface1, Interface2, Interface3 { : }
Example code:
public class Program { public static void main(final String[] args) { final Rectangle myShape = new Rectangle(8, 10, "Red"); myShape.show(); myShape.color("Blue"); myShape.show(); } } interface Shape { public void show(); } interface Colorable { public void color(String color); } class Rectangle implements Shape, Colorable { private final int length; private final int width; private String color; public Rectangle(final int length, final int width, final String color) { this.length = length; this.width = width; this.color = color; } @Override public void show() { System.out.println("A rectangle with length " + this.length + " and width " + this.width + " and color " + this.color); } @Override public void color(final String color) { this.color = color; } }
Polymorphism with Interfaces
A reference to an interface can point to any class that implements that interface.
Colorable myColorable = new Rectangle(8, 10, "Red");
You cannot create an instance of an interface.
// Error: Cannot instantiate the type Shape. Shape myShape = new Shape();
When an interface variable references an object:
Only the methods declared in the interface are available.
Explicit type casting is required to access the other methods referenced by the interface reference.
Example code:
public class Program { public static void main(final String[] args) { final Shape myShape1 = new Square(8, "Red"); myShape1.show(); // myShape1.color(); // Error: The method color() is undefined for the type Shape. // Explicit type casting to Rectangle. final Square myShape2 = (Square) myShape1; myShape2.color("Blue"); myShape2.show(); } } interface Shape { public void show(); } class Square implements Shape { private final int edge; private String color; public Square(final int edge, final String color) { this.edge = edge; this.color = color; } @Override public void show() { System.out.println("A square with edge length " + this.edge + " and color " + this.color); } public void color(final String color) { this.color = color; } }