L11 Inheritance
L11 Inheritance
1
Contents
Motivation: Model classes with similar properties and methods
Declaring a Subclass
Constructor Chaining
Calling Superclass Methods with super
Overriding Methods in the Superclass
The Object Class and Its Methods: toString()
Overloading vs. Overriding
Method Matching vs. Binding
Polymorphism, Dynamic Binding and Generic Programming
Casting Objects and instanceof Operator
The equals method
The ArrayList Class
The MyStack Class
The protected and final Modifiers
2
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Motivation
Model classes with similar properties and methods:
Circles, rectangles
and triangles have many common
features and behaviors (i.e., data fields and methods):
color: String, isFilled: boolean,
dateCreated:Date
getArea(): double
getPerimeter(): double
Inheritance is the mechanism of basing a sub-class on
extending another super-class
Inheritance will help us design and implement classes so to
avoid redundancy
3
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Superclasses and Subclasses
GeometricObject
-color: String The color of the object (default: white).
-filled: boolean Indicates whether the object is filled with a color (default: false).
-dateCreated: java.util.Date The date when the object was created.
+GeometricObject() Creates a GeometricObject.
+GeometricObject(color: String, Creates a GeometricObject with the specified color and filled
filled: boolean) values.
+getColor(): String Returns the color.
+setColor(color: String): void Sets a new color.
+isFilled(): boolean Returns the filled property.
+setFilled(filled: boolean): void Sets a new filled property.
+getDateCreated(): java.util.Date Returns the dateCreated.
+toString(): String Returns a string representation of this object.
Circle Rectangle
-radius: double -width: double
+Circle() -height: double
+Circle(radius: double) +Rectangle()
+Circle(radius: double, color: String, +Rectangle(width: double, height: double)
filled: boolean) +Rectangle(width: double, height: double
+getRadius(): double color: String, filled: boolean)
+setRadius(radius: double): void +getWidth(): double
+getArea(): double +setWidth(width: double): void
+getPerimeter(): double +getHeight(): double
+getDiameter(): double +setHeight(height: double): void
+toString(): String +getArea(): double
+getPerimeter(): double
4
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
public abstract class GeometricObject {
private String color = "white";
private boolean filled;
private java.util.Date dateCreated;
protected GeometricObject() {
dateCreated = new java.util.Date();
}
protected GeometricObject(String color, boolean filled) {
this();
this.color = color;
this.filled = filled;
}
public String getColor() { return color; }
public void setColor(String color) { this.color = color; }
public boolean isFilled() { return filled; }
public void setFilled(boolean filled) { this.filled = filled; }
public java.util.Date getDateCreated() { return dateCreated; }
public String toString() {
return "color: " + color + ", filled: " + filled
+ ", created on " + dateCreated;
}
/** Abstract method getArea */
public abstract double getArea();
/** Abstract method getPerimeter */
public abstract double getPerimeter();
}
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
public class Circle extends GeometricObject {
private double radius;
public Circle() { }
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public String toString() {
return "Circle with radius is " + radius + ", " + super.toString();
}
public double getArea() {
return radius * radius * Math.PI;
}
public double getPerimeter() {
return 2 * radius * Math.PI;
}
public double getDiameter() {
return 2 * radius;
}
}
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
public class Rectangle extends GeometricObject {
private double width;
private double height;
public Rectangle() {
// super();
}
public Rectangle(double width, double height) {
this();
this.width = width;
this.height = height;
}
public Rectangle(double width, double height, String color,
boolean filled) {
super(color,filled);
this.width = width;
this.height = height;
}
public double getWidth() { return width; }
public void setWidth(double width) { this.width = width; }
public double getHeight() { return height; }
public void setHeight(double height) { this.height = height; }
public double getArea() {
return width * height;
}
public double getPerimeter() {
return 2 * (width + height);
} (c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
}
public class TestGeometricObject1 {
public static void main(String[] args) {
// Declare and initialize two geometric objects
GeometricObject geoObject1 = new Circle(5);
GeometricObject geoObject2 = new Rectangle(5, 3);
// Display circle
displayGeometricObject(geoObject1);
// Display rectangle
displayGeometricObject(geoObject2);
System.out.println("The two objects have the same area? " +
equalArea(geoObject1, geoObject2));
}
9
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Are superclass’s Constructor Inherited?
No. They are not inherited.
They are invoked explicitly or implicitly:
Explicitly using the super keyword and the arguments of the superclass
constructors
Implicitly: if the keyword super is not explicitly used, the superclass's
no-arg constructor is automatically invoked as the first statement in the
constructor, unless another constructor is invoked with the keyword
this (in this case, the last constructor in the chain will invoke the
superclass constructor)
public A(args) { public A(args) {
// some statements is equivalent to
super();
} // some statements
}
10
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
The Keyword super
The keyword super refers to the superclass of
the class in which super appears
This keyword is used in two ways:
To call a superclass constructor (through
constructor chaining)
To call a superclass method (hidden by the
overriding method)
11
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Constructor Chaining
• Constructor chaining : constructing an instance of a class invokes
all the superclasses’ constructors along the inheritance chain.
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
class Employee extends Person {
public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}
public Employee(String s) {
System.out.println(s);
}
}
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
12 }
} (c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty(); 1. Start from the
} main method
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
public Employee(String s) {
System.out.println(s);
}
}
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
13
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty(); 2. Invoke Faculty
} constructor
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
public Employee(String s) {
System.out.println(s);
}
}
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
14
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}
public Employee(String s) {
System.out.println(s);
}
}
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
15
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
4. Invoke Employee(String)
class Employee extends Person { constructor
public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}
public Employee(String s) {
System.out.println(s);
}
}
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
16
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
17
5. Invoke Person() constructor
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
} 6. Execute println
18
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
7. Execute println
class Employee extends Person {
public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
19
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
8. Execute println
class Employee extends Person {
public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}
class Person {
public Person() {
System.out.println("(1) Person's no-arg constructor is invoked");
}
}
20
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Execution
public class Faculty extends Employee {
public static void main(String[] args) {
new Faculty();
}
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
9. Execute println
class Employee extends Person {
public Employee() {
this("(2) Invoke Employee’s overloaded constructor");
System.out.println("(3) Employee's no-arg constructor is invoked");
}
public Faculty() {
System.out.println("(4) Faculty's no-arg constructor is invoked");
}
}
23
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Overriding Methods in the Superclass
Method overriding: modify in the subclass the
implementation of a method defined in the superclass:
public abstract class GeometricObject {
...
public String toString() {
return "color: " + color + ", filled: " + filled
+ ", date created: " + getDateCreated();
}
}
class Circle extends GeometricObject {
...
public String toString() {
return "Circle with radius " + radius
+ ", " + super.toString();
}
}
24
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
The Object Class and Its Methods
Every class in Java is descended from the
java.lang.Object class
If no inheritance is specified when a class is
defined, the superclass of the class is
java.lang.Object
public class GeometricObject { public class GeometricObject extends Object{
... Equivalent ...
} }
25
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
The toString() method in Object
The toString() method returns a string representation of
the object
The default Object implementation returns a string consisting
of a class name of which the object is an instance, the @ ("at")
sign, and a number representing this object
Loan loan = new Loan();
System.out.println(loan.toString());
The code displays something like Loan@12345e6
you should override the toString() method so that it returns an
informative string representation of the object
26
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Overriding is different than Overloading
Method overloading (discussed in Methods) is the ability to create
multiple methods of the same name, but with different signatures
and implementations:
public class Overloading {
public static int max(int num1, int num2) {
if (num1 > num2)
return num1;
return num2;
}
public static double max(double num1, double num2) {
if (num1 > num2)
return num1;
return num2;
}
public static void main(String[] args) {
System.out.println(max(1, 2)); // 2 (as an int)
System.out.println(max(1, 2.3)); // 2.3 (as a double)
}
}
Method overriding requires that the subclass has the same method signature as
27 in the superclass.
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Overloading vs. Overriding
public class Test { public class Test {
public static void main(String[] args) { public static void main(String[] args) {
B a = new A(); B a = new A();
a.p(10.0); 20.0 a.p(10.0); 10.0
a.p(10); 10 a.p(10); 10.0
} }
} }
class B { class B {
public void p(double i) { public void p(double i) {
System.out.println(i * 2); System.out.println(i * 2);
} }
} }
28
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Method Matching vs. Binding
For overloaded methods, the compiler finds
a matching method according to parameter
type, number of parameters, and order of the
parameters at compilation time.
For overridden methods, the Java Virtual
Machine dynamically binds the
implementation of the most specific
overridden method implementation at
runtime.
29
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Polymorphism, Dynamic Binding and Generic Programming
public class PolymorphismDemo { Polymorphism: an object of a subtype can
public static void main(String[] args) { be used wherever its supertype value is
m(new GraduateStudent());
m(new Student()); required:
m(new Person());
m(new Object()); The method m takes a parameter of the
} Object type, so can be invoked with
public static void m(Object x) { any object.
System.out.println(x.toString());
} Dynamic binding: the Java Virtual Machine
}
class GraduateStudent
determines dynamically at runtime which
extends Student { implementation is used by the method:
} When the method m(Object x) is
class Student extends Person {
public String toString() {
executed, the argument x’s most specific
return "Student"; toString() method is invoked.
}
} Output:
class Person /*extends Object*/ { Student
public String toString() {
return "Person"; Student
} Person
} java.lang.Object@12345678
30
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Dynamic Binding
Suppose an object o is an instance of classes C1 Cn
(o=new C1()) where C1 is a subclass of C2,
C2 is a subclass of C3, ..., and Cn-1 is a Cn-1
subclass of Cn
Cn is the most general class (i.e., Object), and …
33
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Why Explicit Casting Is Necessary?
Sometimes we need to cast down, so we can use methods
of the subclass (e.g., getGPA())
Student b = o; // Syntax Error
A compilation error would occur because an Object o
is not necessarily an instance of Student
35
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
public class CastingDemo{
public static void main(String[] args){
Object object1 = new Circle(1);
Object object2 = new Rectangle(1, 1);
displayObject(object1);
displayObject(object2);
}
public static void displayObject(Object object) {
if (object instanceof Circle) {
System.out.println("The circle radius is " +
((Circle)object).getRadius());
System.out.println("The circle diameter is " +
((Circle)object).getDiameter());
}else if (object instanceof Rectangle) {
System.out.println("The rectangle width is " +
((Rectangle)object).getWidth());
}
}
36
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
}
The equals method
The equals()method compares the contents of two
objects - the default implementation of the equals
method in the Object class is as follows:
public boolean equals(Object obj) {
return (this == obj);
}
Override the equals()method in other classes (e.g.,
Circle):
public boolean equals(Object o) {
if (o instanceof Circle)
return radius == ((Circle)o).radius;
// && super.equals(o);
else return false;
37
} (c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Generic Programming
public class PolymorphismDemo { Generic programming:
public static void main(String[] args) {
m(new GraduateStudent());
polymorphism allows methods to
m(new Student()); be used generically for a wide
m(new Person());
m(new Object());
range of object arguments:
}
public static void m(Object x) {
- if a method’s parameter type is a
System.out.println(x.toString()); superclass (e.g.,Object), you
}
}
may pass an object to this
class GraduateStudent extends Student { method of any of the
}
class Student extends Person { parameter’s subclasses (e.g.,
public String toString() { Student or String) and the
return "Student";
} particular implementation of
} the method of the object that is
class Person extends Object {
public String toString() { invoked is determined
}
return "Person"; dynamically
} - very useful for data-structures
38
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
The ArrayList Class
You can create arrays to store objects - But the array’s size is fixed once the
array is created.
Java provides the java.util.ArrayList class that can be used to
store an unlimited finite number of objects:
java.util.ArrayList
+ArrayList() Creates an empty list.
+add(o: Object) : void Appends a new element o at the end of this list.
+add(index: int, o: Object) : void Adds a new element o at the specified index in this list.
+clear(): void Removes all the elements from this list.
+contains(o: Object): boolean Returns true if this list contains the element o.
+get(index: int) : Object Returns the element from this list at the specified index.
+indexOf(o: Object) : int Returns the index of the first matching element in this list.
+isEmpty(): boolean Returns true if this list contains no elements.
+lastIndexOf(o: Object) : int Returns the index of the last matching element in this list.
+remove(o: Object): boolean Removes the element o from this list.
+size(): int Returns the number of elements in this list.
+remove(index: int) : Object Removes the element at the specified index.
+set(index: int, o: Object) : Object Sets the element at the specified index.
39
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
public class TestArrayList {
public static void main(String[] args) { // Warnings
java.util.ArrayList cityList = new java.util.ArrayList();
cityList.add("London");cityList.add("New York");cityList.add("Paris");
cityList.add("Toronto");cityList.add("Hong Kong");
System.out.println("List size? " + cityList.size());
System.out.println("Is Toronto in the list? " +
cityList.contains("Toronto"));
System.out.println("The location of New York in the list? " +
cityList.indexOf("New York"));
System.out.println("Is the list empty? " + cityList.isEmpty()); // false
cityList.add(2, "Beijing");
cityList.remove("Toronto");
for (int i = 0; i < cityList.size(); i++)
System.out.print(cityList.get(i) + " ");
System.out.println();
// Create a list to store two circles
java.util.ArrayList list = new java.util.ArrayList();
list.add(new Circle(2));
list.add(new Circle(3));
System.out.println( ((Circle)list.get(0)).getArea() );
40}
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
}
public class TestArrayList { // Generics: eliminates warnings
public static void main(String[] args) {
java.util.ArrayList<String> cityList=new java.util.ArrayList<String>();
cityList.add("London");cityList.add("New York");cityList.add("Paris");
cityList.add("Toronto");cityList.add("Hong Kong");
System.out.println("List size? " + cityList.size());
System.out.println("Is Toronto in the list? " +
cityList.contains("Toronto"));
System.out.println("The location of New York in the list? " +
cityList.indexOf("New York"));
System.out.println("Is the list empty? " + cityList.isEmpty()); // false
cityList.add(2, "Beijing");
cityList.remove("Toronto");
for (int i = 0; i < cityList.size(); i++)
System.out.print(cityList.get(i) + " ");
System.out.println();
// Create a list to store two circles
java.util.ArrayList<Circle> list = new java.util.ArrayList<Circle>();
list.add(new Circle(2));
list.add(new Circle(3));
System.out.println( list.get(0).getArea() ); // no casting needed
41}
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
}
Our MyStack Class – Custom stack
A stack to hold any objects.
MyStack
-list: ArrayList A list to store elements.
+isEmpty(): boolean Returns true if this stack is empty.
+getSize(): int Returns the number of elements in this stack.
+peek(): Object Returns the top element in this stack.
+pop(): Object Returns and removes the top element in this stack.
+push(o: Object): void Adds a new element to the top of this stack.
+search(o: Object): int Returns the position of the first element in the stack from
the top that matches the specified element.
42
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
public class MyStack {
private java.util.ArrayList list = new java.util.ArrayList();
public void push(Object o) {
list.add(o);
}
public Object pop() {
Object o = list.get(getSize() - 1);
list.remove(getSize() - 1);
return o;
}
public Object peek() {
return list.get(getSize() - 1);
}
public int search(Object o) {
return list.lastIndexOf(o);
}
public boolean isEmpty() {
return list.isEmpty();
}
public int getSize() {
return list.size();
}
public String toString() {
return "stack: " + list.toString();
}
}
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
public class TestMyStack {
public static void main(String[] args){
MyStack s = new MyStack();
s.push(1);
s.push(2);
System.out.println(s.pop()); // 2
System.out.println(s.pop()); // 1
MyStack s2 = new MyStack();
s2.push("New York");
s2.push("Washington");
System.out.println(s2.pop()); // New York
System.out.println(s2.pop()); // Washington
}
}
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
The protected Modifier
A protected data or a protected method in a
public class can be accessed by any class in the
same package or its subclasses, even if the
subclasses are in a different package
Visibility increases
45
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Accessibility Summary
Modifier Accessed Accessed Accessed Accessed
on members from the from the from a from a different
in a class same class same package subclass package
public
protected -
default - -
private - - -
46
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Visibility Modifiers
package p1;
public class C1 { public class C2 {
public int x; C1 o = new C1();
protected int y; can access o.x;
int z; can access o.y;
private int u; can access o.z;
cannot access o.u;
protected void m() {
} can invoke o.m();
} }
package p2;
47
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
UML Class Diagram
Visibility:
+ = public
- = private
~ = default/package
# = protected
underlined = static
48
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
A Subclass Cannot Weaken the Accessibility
A subclass may override a protected method
in its superclass and change its visibility to
public.
However, a subclass cannot weaken the accessibility
of a method defined in the superclass.
For example, if a method is defined as public in the
superclass, it must be defined as public in the
subclass.
49
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
Overriding Methods in the Subclass
An instance method can be overridden only if it is accessible
A private method cannot be overridden, because it is
not accessible outside its own class
If a method defined in a subclass is private in its superclass,
the two methods are completely unrelated
A static method can be inherited
A static method cannot be overridden
If a static method defined in the superclass is redefined in a
subclass, the method defined in the superclass is hidden
50
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)
The final Modifier
Remember that a final variable is a constant:
final static double PI = 3.14159;
51
(c) Pearson Education, Inc. & Paul Fodor (CS Stony Brook)