CS计算机代考程序代写 prolog data structure compiler Java ITI 1121. Introduction to Computing II – subtitle

ITI 1121. Introduction to Computing II – subtitle

ITI 1121. Introduction to Computing II
Inheritance: polymorphism

by

Marcel Turcotte

Version February 8, 2020

Preamble

Preamble

Overview

Overview

Inheritance: polymorphism

The concept of inheritance in Java promotes code reuse and supports the notion of
polymorphism.

General objective:
This week you will be able to create polymorphic methods.

1 69

Preamble

Learning objectives

Learning objectives

Describe the concept of polymorphism.
Create polymorphic methods.
Compare the interface and the abstract class.

Lectures:
Pages 7–31, 39–45 of E. Koffman and P. Wolfgang.

2 69

Preamble

Plan

Plan

1 Preamble

2 Polymorphism

3 Inheritance and Java

4 Prologue

3 69

Polymorphism

Polymorphism

From the Greek polus = several and morphê = forms, so it means which has
several forms.

4 69

Definitions

In computer science, polymorphism consists in allowing the use of an identifier for
different entities (see different types).
1. Polymorphism ad hoc (name overloading): the same method name is associated

with different blocks of code. These methods have the same name, but they differ by
their list of parameters.

2. Subtype polymorphism (by inheritance): an identifier is linked to data of different
types by a subtype relationship.

3. Parametric polymorphism (generic): the class has one or more formal type
parameters.

5 69

Overloading

The PrintStream class uses ad hoc polymorphism to implement the println method.

p r i n t l n ( )
p r i n t l n ( boolean v a l u e )
p r i n t l n ( char v a l u e )
p r i n t l n ( char [ ] v a l u e )
p r i n t l n ( double v a l u e )
p r i n t l n ( f l o a t v a l u e )
p r i n t l n ( i n t v a l u e )
p r i n t l n ( long v a l u e )

6 69

Name overloading (continued)

Three methods having different signatures ∗.

pub l i c s t a t i c i n t sum( i n t a , i n t b , i n t c ) {
re tu rn a + b + c ;

}
pub l i c s t a t i c i n t sum( i n t a , i n t b ) {

re tu rn a + b ;
}
pub l i c s t a t i c double sum( double a , double b ) {

re tu rn a + b ;
}

∗In Java, the signature of a method includes the method name and the parameter list, but not the
return value.

7 69

Polymorphism by subtype

Problem : implement a method isLeftOf which returns true if this shape is located to
the left of its argument (another geometric shape) and false otherwise.

8 69

isLeftOf

C i r c l e c1 , c2 ;
c1 = new C i r c l e ( 1 0 . 0 , 20 . 0 , 5 . 0 ) ;
c2 = new C i r c l e ( 2 0 . 0 , 10 . 0 , 5 . 0 ) ;

i f ( c1 . i s L e f tO f ( c2 ) ) {
System . out . p r i n t l n ( ” c1 i s L e f tO f c2 ” ) ;

} e l s e {
System . out . p r i n t l n ( ” c2 i s L e f tO f c1 ” ) ;

}

9 69

isLeftOf

Rec tang l e r1 , r2 ;
r1 = new Rec tang l e ( 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 ) ;
r2 = new Rec tang l e ( 100 . 0 , 100 .0 , 200 .0 , 4 0 0 . 0 ) ;

i f ( r1 . i s L e f tO f ( r2 ) ) {
System . out . p r i n t l n ( ” r1 i s L e f tO f r2 ” ) ;

} e l s e {
System . out . p r i n t l n ( ” r2 i s L e f tO f r1 ” ) ;

}

10 69

isLeftOf

i f ( r1 . i s L e f tO f ( c1 ) ) {
System . out . p r i n t l n ( ” r1 i s L e f tO f c1 ” ) ;

} e l s e {
System . out . p r i n t l n ( ” c1 i s L e f tO f r1 ” ) ;

}

i f ( c2 . i s L e f tO f ( r2 ) ) {
System . out . p r i n t l n ( ” c2 i s L e f tO f r2 ” ) ;

} e l s e {
System . out . p r i n t l n ( ” r2 i s L e f tO f c2 ” ) ;

}

11 69

An outrageous solution!

pub l i c boolean i s L e f tO f ( C i r c l e c ) {
re tu rn getX ( ) < c . getX ( ) ; } pub l i c boolean i s L e f tO f ( Rec tang l e r ) { re tu rn getX ( ) < r . getX ( ) ; } Why? 12 69 An outrageous solution! pub l i c boolean i s L e f tO f ( C i r c l e c ) { re tu rn getX ( ) < c . getX ( ) ; } pub l i c boolean i s L e f tO f ( Rec tang l e r ) { re tu rn getX ( ) < r . getX ( ) ; } As many implementations as there are varieties of shapes! Yet, all the implementations are identical! Whenever a new category of shape is defined (say Triangle), a new method isLeftOf must be created! 13 69 Solution Suggestions? pub l i c boolean i s L e f tO f ( "Any Shape " s ) { re tu rn getX ( ) < s . getX ( ) ; } How to write any “Any Shape” in Java? 14 69 Solution Let’s implement the isLeftOf method in the Shape class as follows. pub l i c boolean i s L e f tO f ( Shape s ) { re tu rn getX ( ) < s . getX ( ) ; } 15 69 isLeftOf C i r c l e c ; c = new C i r c l e ( 1 0 . 0 , 20 . 0 , 5 . 0 ) ; Rec tang l e r ; r = new Rec tang l e ( 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 ) ; i f ( c . i s L e f tO f ( r ) ) { System . out . p r i n t l n ( " c i s L e f tO f r " ) ; } e l s e { System . out . p r i n t l n ( " r i s L e f tO f c " ) ; } 16 69 isLeftOf i f ( c . i s L e f tO f ( r ) ) { // . . . The method isLeftOf of the object designated by the reference c is called. Perfect, c designates an object of the class Circle, the latter inherits the method isLeftOf. 17 69 isLeftOf i f ( c . i s L e f tO f ( r ) ) { // . . . Um, during the call, the value of the actual parameter, r, is copied to the formal parameter, s. Should we conclude that the following statements are also valid? Shape s ; Rec tang l e r ; r = new Rec tang l e ( 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 ) ; s = r ; 18 69 Types “A variable is a storage location and has an associated type, sometimes called its compile-time type, that is either a primitive type (§4.2) or a reference type (§4.3). A variable always contains a value that is assignment compatible (§5.2) with its type.” “Assignment of a value of compile-time reference type S (source) to a variable of compile-time reference type T (target) is checked as follows: If S is a class type: If T is a class type, then S must either be the same class as T, or S must be a subclass of T, or a compile-time error occurs.” ⇒ Gosling et al. (2000) The Java Language Specification. 19 69 isLeftOf Indeed, this definition confirms that the following statements are valid. Shape s ; Rec tang l e r ; r = new Rec tang l e ( 0 . 0 , 0 . 0 , 1 . 0 , 1 . 0 ) ; s = r ; but not “r = s”! 20 69 Polymorphism A variable s designates an object of the class Shape or one of its subclasses. Shape s ; Utilisation: s = new C i r c l e ( 0 . 0 , 0 . 0 , 1 . 0 ) ; s = new Rec tang l e ( 1 0 . 0 , 100 .0 , 10 . 0 , 1 0 0 . 0 ) ; 21 69 Polymorphism pub l i c boolean i s L e f tO f ( Shape o th e r ) { boolean r e s u l t ; i f ( getX ( ) < o the r . getX ( ) ) { r e s u l t = t rue ; } e l s e { r e s u l t = f a l s e ; } re tu rn r e s u l t ; } Usage: C i r c l e c = new C i r c l e ( 1 0 . 0 , 10 . 0 , 5 . 0 ) ; Rec tang l e d = new Rec tang l e ( 0 . 0 , 10 . 0 , 12 . 0 , 2 4 . 0 ) ; i f ( c . i s L e f tO f ( d ) ) { . . . } 22 69 Exercises Shape s ; C i r c l e c ; c = new C i r c l e ( 0 . 0 , 0 . 0 , 1 . 0 ) ; s = c ; i f ( c . getX ( ) ) { . . . } // v a l i d ? i f ( s . getX ( ) ) { . . . } // v a l i d ? i f ( c . g e tRad iu s ( ) ) { . . . } // v a l i d ? i f ( s . g e tRad iu s ( ) ) { . . . } // v a l i d ? 23 69 Remarks Shape s ; C i r c l e c ; c = new C i r c l e ( 0 . 0 , 0 . 0 , 1 . 0 ) ; s = c ; The object designated by s remains a circle (Circle). The class of an object remains the same throughout the execution of the program. 24 69 Remarks Shape s ; C i r c l e c ; c = new C i r c l e ( 0 . 0 , 0 . 0 , 1 . 0 ) ; s = c ; i f ( s . getX ( ) ) { . . . } When we use s to designate a circle (Circle), the object “is seen as” a geometrical shape (Shape), in the sense that we only see the characteristics (methods and variables) defined in the class Shape. 25 69 Remarks Polymorphism is a powerful concept. The method isLeftOf that we have defined can be used not only to handle circles and rectangles, but also any object of a future subclass of the class Shape. pub l i c c l a s s Tr i a n g l e extends Shape { // . . . } 26 69 Calculating the area Problem : We want all geometric shapes (objects in the subclasses of Shape) to have a method for calculating the area. 27 69 What do you mean, Marcel? pub l i c c l a s s Shape { // . . . pub l i c i n t compareTo ( Shape o th e r ) { i f ( a r ea ( ) < o the r . a r ea ( ) ) { re tu rn −1; } e l s e i f ( a r ea ( ) == othe r . a r ea ( ) ) { re tu rn 0 ; } e l s e { re tu rn 1 ; } } } 28 69 What do you think? pub l i c c l a s s Shape { // . . . // Must be r e d e f i n e d by the s u b c l a s s e s o r e l s e . . . pub l i c double a r ea ( ) { re tu rn −1.0; } pub l i c i n t compareTo ( Shape o th e r ) { i f ( a r ea ( ) < o the r . a r ea ( ) ) { re tu rn −1; } e l s e i f ( a r ea ( ) == othe r . a r ea ( ) ) { re tu rn 0 ; } e l s e { re tu rn 1 ; } } } 29 69 Abstract pub l i c c l a s s Shape { // . . . pub l i c abs t rac t double a r ea ( ) ; pub l i c i n t compareTo ( Shape o th e r ) { i f ( a r ea ( ) < o the r . a r ea ( ) ) { re tu rn −1; } e l s e i f ( a r ea ( ) == othe r . a r ea ( ) ) { re tu rn 0 ; } e l s e { re tu rn 1 ; } } } 30 69 Abstract pub l i c abs t rac t c l a s s Shape { // . . . pub l i c abs t rac t double a r ea ( ) ; pub l i c i n t compareTo ( Shape o th e r ) { i f ( a r ea ( ) < o the r . a r ea ( ) ) { re tu rn −1; } e l s e i f ( a r ea ( ) == othe r . a r ea ( ) ) { re tu rn 0 ; } e l s e { re tu rn 1 ; } } } 31 69 Abstract classes A class declaring an abstract method must be abstract. You can’t create objects of an abstract class. A class can be declared abstract, even if it does not contain abstract methods. 32 69 What have we achieved? pub l i c c l a s s C i r c l e extends Shape { } Circle.java:1: Circle is not abstract and does not override abstract method area() in Shape public class Circle extends Shape { ^ 1 error 33 69 pub l i c c l a s s C i r c l e extends Shape { p r i v a t e double r a d i u s ; pub l i c C i r c l e ( double r a d i u s ) { t h i s . r a d i u s = r a d i u s ; } pub l i c double ge tRad iu s ( ) { re tu rn r a d i u s ; } pub l i c double a r ea ( ) { re tu rn Math . PI ∗ r a d i u s ∗ r a d i u s ; } pub l i c vo id s c a l e ( double f a c t o r ) { r a d i u s ∗= f a c t o r ; } } Name lookup + getId() : long Account + getBalance() : double + getMonthlyFees() : double BankAccount CheckingAccount + getMonthlyFees() : double SavingAccount BankAccount and SavingAccount both have a method named getMonthlyFees. 35 69 BankAccount: pub l i c double getMonth lyFees ( ) { re tu rn 2 5 . 0 ; } SavingAccount: pub l i c double getMonth lyFees ( ) { double r e s u l t ; i f ( ge tBa l ance ( ) > 5000 .0 ) {

r e s u l t = 0 . 0 ;
} e l s e {

r e s u l t = super . ge tMonth lyFees ( ) ;
}
re tu rn r e s u l t ;

}

Consider the following statements:

Account a ;

BankAccount b ;

Sav ingAccount s ;

s = new Sav ingAccount ( ) ;
s . ge tMonth lyFees ( ) ;

b = s ;
b . getMonth lyFees ( ) ;

a = b ;
a . getMonth lyFees ( ) ;

Dynamic binding

Let S (source) be the type of the object currently designated by a reference variable
of type T (target).
Unless the method is static or final, the lookup
1. occurs at runtime, and
2. starts at the class S:

if the method is found, this is the method that will be executed,
otherwise the immediate superclass is considered,
this process continues until the first occurrence of the method is found.

⇒ A.K.A. late binding or virtual binding

38 69

Inheritance and Java

Object

In Java, classes are organized in a tree structure. The most general class, the one at
the root of the tree, is called Object.

Object
#clone(): Object
+equals(Object:obj): boolean
+getClass(): Class
+toString(): String

Number
+byteValue(): byte
+doubleValue(): double
+floatValue(): float
+intValue(): int
+longValue(): long
+shortValue()

Integer
+MAX_VALUE: int
+MIN_VALUE: int

+byteValue(): byte
+doubleValue(): double
+floatValue(): float
+intValue(): int
+longValue(): long
+shortValue()
+compareTo(i:integer): int
+parseInt(s:String): int
+toString(): String

Double
+MAX_VALUE: double
+MIN_VALUE: double

+byteValue(): byte
+doubleValue(): double
+floatValue(): float
+intValue(): int
+longValue(): long
+shortValue()
+compareTo(d:Double): int
+parseDouble(s:String): double
+toString(): String

39 69

Object

If the superclass is not explicitly mentioned, Object is the default superclass, so the
following statement:

pub l i c c l a s s C {

}

is equivalent to this one:
pub l i c c l a s s C extends Object {

}

40 69

equals

The class Object defines a method equals.
Every Java object therefore has a method equals.
So we can always write a.equals(b) if a and b are reference variables.

Object
#clone(): Object
+equals(Object:obj): boolean
+getClass(): Class
+toString(): String

Number
+byteValue(): byte
+doubleValue(): double
+floatValue(): float
+intValue(): int
+longValue(): long
+shortValue()

Integer
+MAX_VALUE: int
+MIN_VALUE: int

+byteValue(): byte
+doubleValue(): double
+floatValue(): float
+intValue(): int
+longValue(): long
+shortValue()
+compareTo(i:integer): int
+parseInt(s:String): int
+toString(): String

Double
+MAX_VALUE: double
+MIN_VALUE: double

+byteValue(): byte
+doubleValue(): double
+floatValue(): float
+intValue(): int
+longValue(): long
+shortValue()
+compareTo(d:Double): int
+parseDouble(s:String): double
+toString(): String

41 69

equals

This is the equals method of the Object class.

pub l i c boolean e qua l s ( Object ob j ) {
re tu rn ( t h i s == ob j ) ;

}

42 69

Account

pub l i c c l a s s Account {

p r i v a t e i n t i d ;
p r i v a t e S t r i n g name ;

pub l i c Account ( i n t id , S t r i n g name) {
t h i s . i d = i d ;
t h i s . name = name ;

}
}

43 69

Test

pub l i c c l a s s Test {
pub l i c s t a t i c vo id main ( S t r i n g [ ] a r g s ) {

Account a , b ;
a = new Account (1 , new S t r i n g ( “Marce l ” ) ) ;
b = new Account (1 , new S t r i n g ( “Marce l ” ) ) ;
i f ( a . e qu a l s ( b ) ) {

System . out . p r i n t l n ( ” a and b a r e e qua l s ” ) ;
} e l s e {

System . out . p r i n t l n ( ” a and b a r e not e qua l s ” ) ;
}

}
}

What will the result be?

44 69

pub l i c c l a s s Account {
p r i v a t e i n t i d ;
p r i v a t e S t r i n g name ;
pub l i c Account ( i n t id , S t r i n g name) {

t h i s . i d = i d ;
t h i s . name = name ;

}
pub l i c boolean e qua l s ( Object o ) {

boolean r e s u l t = t rue ;
i f ( o == nu l l ) { // <−−− r e s u l t = f a l s e ; } . . . re tu rn r e s u l t ; } } pub l i c c l a s s Account { p r i v a t e i n t i d ; p r i v a t e S t r i n g name ; pub l i c Account ( i n t id , S t r i n g name) { t h i s . i d = i d ; t h i s . name = name ; } pub l i c boolean e qua l s ( Object o ) { boolean r e s u l t = t rue ; i f ( o == nu l l ) { r e s u l t = f a l s e ; } e l s e i f ( t h i s . g e tC l a s s ( ) != o . g e tC l a s s ( ) ) { // <−−− r e s u l t = f a l s e ; } . . . re tu rn r e s u l t ; } } pub l i c c l a s s Account { p r i v a t e i n t i d ; p r i v a t e S t r i n g name ; pub l i c Account ( i n t id , S t r i n g name) { . . . } pub l i c boolean e qua l s ( Object o ) { boolean r e s u l t = t rue ; i f ( o == nu l l ) { r e s u l t = f a l s e ; } e l s e i f ( t h i s . g e tC l a s s ( ) != o . g e tC l a s s ( ) ) { r e s u l t = f a l s e ; } e l s e { Account o th e r = ( Account ) o ; // <−−− . . . } re tu rn r e s u l t ; } } pub l i c c l a s s Account { p r i v a t e i n t i d ; p r i v a t e S t r i n g name ; pub l i c Account ( i n t id , S t r i n g name) { . . . } pub l i c boolean e qua l s ( Object o ) { boolean r e s u l t = t rue ; i f ( o == nu l l ) { r e s u l t = f a l s e ; } e l s e i f ( t h i s . g e tC l a s s ( ) != o . g e tC l a s s ( ) ) { r e s u l t = f a l s e ; } e l s e { Account o th e r = ( Account ) o ; i f ( i d != o th e r . i d ) { r e s u l t = f a l s e ; } e l s e i f ( name == nu l l && othe r . name != nu l l ) { r e s u l t = f a l s e ; } e l s e i f ( name != nu l l && ! name . e qua l s ( o t h e r . name) ) { r e s u l t = f a l s e ; } } re tu rn r e s u l t ; } } Test pub l i c c l a s s Test { pub l i c s t a t i c vo id main ( S t r i n g [ ] a r g s ) { Account a , b ; a = new Account (1 , new S t r i n g ( "Marce l " ) ) ; b = new Account (1 , new S t r i n g ( "Marce l " ) ) ; i f ( a . e qu a l s ( b ) ) { System . out . p r i n t l n ( " a and b a r e e qua l s " ) ; } e l s e { System . out . p r i n t l n ( " a and b a r e not e qua l s " ) ; } } } What will the result be? 49 69 toString() Since the class Object declares a method toString(), all objects have this method. Either the class inherits a method toString() or it redefines it. Thus, the statement a.toString() is always valid if a is a reference variable. 50 69 toString() Account a ; a = new Account (101 , "Marce l " ) ; System . out . p r i n t l n ( a ) ; System . out . p r i n t l n ( a . t o S t r i n g ( ) ) ; 51 69 System.out.println pub l i c c l a s s Pr in tS t r eam { // . . . pub l i c vo id p r i n t l n ( Object ob j ) { w r i t e ( S t r i n g . va lueOf ( ob j ) ) ; } } pub l i c c l a s s S t r i n g { // . . . pub l i c s t a t i c S t r i n g va lueOf ( Object ob j ) { re tu rn ( ob j == nu l l ) ? " n u l l " : ob j . t o S t r i n g ( ) ; } } 52 69 pub l i c c l a s s Account { p r i v a t e i n t i d ; p r i v a t e S t r i n g name ; pub l i c Account ( i n t id , S t r i n g name) { . . . } // . . . } toString() Account a ; a = new Account (101 , "Marce l " ) ; System . out . p r i n t l n ( a ) ; > java Test
Account@3fee733d

54 69

toString()

Since the class Object declares a method toString(), all objects have this method.
Either the class inherits a method toString() or it redefines it.
Thus, the statement a.toString() is always valid if a is a reference variable.

pub l i c c l a s s Object {

// . . .

pub l i c S t r i n g t o S t r i n g ( ) {
re tu rn g e tC l a s s ( ) . getName()+”@”+I n t e g e r . t oHexS t r i ng ( hashCode ( ) ) ;

}
}

55 69

pub l i c c l a s s Account {

p r i v a t e i n t i d ;
p r i v a t e S t r i n g name ;

pub l i c Account ( i n t id , S t r i n g name) { . . . }

// . . .

pub l i c S t r i n g t o S t r i n g ( ) {
re tu rn ” Account : i d = ” + i d + ” , name = ” + name ;

}
}

toString()

Account a ;
a = new Account (101 , “Marce l ” ) ;
System . out . p r i n t l n ( a ) ;

> java Test
Account: id = 101, name = Marcel

57 69

Example
import j a v a . awt . Te x tF i e l d ;

pub l i c c l a s s TimeF ie ld extends Tex tF i e l d {
pub l i c Time getTime ( ) {

re tu rn Time . parseTime ( getText ( ) ) ;
}

}

// java.lang.Object
// |
// +–java.awt.Component
// |
// +–java.awt.TextComponent
// |
// +–java.awt.TextField
// |
// +–TimeField

58 69

instanceof

Occasionally, one wants to determine whether a (polymorphic) variable designates an
object of a given class or one of its subclasses.

We then use the operator instanceof or the instance method isInstance.
If, on the other hand, one wants to know if a (polymorphic) variable designates an
object of a certain class, but not one of its subclasses, then use this.getClass() ==
other.getClass().

59 69

pub l i c c l a s s Test {
pub l i c s t a t i c vo id main ( S t r i n g [ ] a r g s ) {

Shape [ ] shapes = new Shape [ 5 ] ;
Shape s = new C i r c l e ( 100 . 0 , 200 .0 , 1 0 . 0 ) ;

shapes [ 0 ] = s ;
shapes [ 1 ] = nu l l ;
shapes [ 2 ] = new Rec tang l e ( 5 0 . 0 , 50 . 0 , 10 . 0 , 1 5 . 0 ) ;
shapes [ 3 ] = new C i r c l e ( ) ;
shapes [ 4 ] = new Rec tang l e ( ) ;

i n t count = 0 ;

f o r ( Shape shape : shapes ) {
i f ( shape i n s t anceo f C i r c l e ) {

count++;
}

}

System . out . p r i n t l n ( ” There a r e ” + count + ” c i r c l e s ” ) ;
}

}

pub l i c c l a s s Test {
pub l i c s t a t i c vo id main ( S t r i n g [ ] a r g s ) {

Shape [ ] shapes = new Shape [ 5 ] ;
Shape s = new C i r c l e ( 100 . 0 , 200 .0 , 1 0 . 0 ) ;

shapes [ 0 ] = s ;
shapes [ 1 ] = nu l l ;
shapes [ 2 ] = new Rec tang l e ( 5 0 . 0 , 50 . 0 , 10 . 0 , 1 5 . 0 ) ;
shapes [ 3 ] = new C i r c l e ( ) ;
shapes [ 4 ] = new Rec tang l e ( ) ;

i n t count = 0 ;

f o r ( Shape shape : shapes ) {
i f ( shape != nu l l && shape . i s I n s t a n c e o f ( s ) ) {

count++;
}

}

System . out . p r i n t l n ( ” There a r e ” + count + ” c i r c l e s ” ) ;
}

}

Implementation to be avoided!

On the next page, the example uses getClass().getName().equals(“Circle”).
This solution offers no type safety.

If I make a typo in the class name for the parameter to the method equals, it is still a
well-formed string, it will be compiled, but the program will not work as expected.

With the first two approaches, this error is detected at compile time.
Later, if I change the class name (“refactor”) to Cercle (French for “circle”), with the
first two approaches, the compiler will find all cases where I use “ref instanceof
Circle”, but not getClass().getName().equals(“Circle”).

62 69

pub l i c c l a s s Test {
pub l i c s t a t i c vo id main ( S t r i n g [ ] a r g s ) {

Shape [ ] shapes = new Shape [ 5 ] ;
Shape s = new C i r c l e ( 100 . 0 , 200 .0 , 1 0 . 0 ) ;

shapes [ 0 ] = s ;
shapes [ 1 ] = nu l l ;
shapes [ 2 ] = new Rec tang l e ( 5 0 . 0 , 50 . 0 , 10 . 0 , 1 5 . 0 ) ;
shapes [ 3 ] = new C i r c l e ( ) ;
shapes [ 4 ] = new Rec tang l e ( ) ;

i n t count = 0 ;

f o r ( Shape shape : shapes ) {
i f ( shape . g e tC l a s s ( ) . getName . e qua l s ( ” C i r c l e ” ) ) {

count++;
}

}

System . out . p r i n t l n ( ” There a r e ” + count + ” c i r c l e s ” ) ;
}

}

getClass()

The contract of the method equals requires that the method be symmetrical. That
is, a.equals(b) and b.equals(a) gives the same result.
If instanceof were used, this property might not be verified in the context of a class
hierarchy where the method equals is redefined in a subclass.
It is therefore preferable to use this.getClass() == other.getClass(), as shown on
the next page.
https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/
lang/Object.html

64 69

https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/Object.html
https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/Object.html

pub l i c c l a s s Account {
p r i v a t e i n t i d ; p r i v a t e S t r i n g name ;
pub l i c Account ( i n t id , S t r i n g name) { . . . }
pub l i c boolean e qua l s ( Object o ) {

boolean r e s u l t = t rue ;
i f ( o == nu l l ) {

r e s u l t = f a l s e ;
} e l s e i f ( t h i s . g e tC l a s s ( ) != o . g e tC l a s s ( ) ) {

r e s u l t = f a l s e ;
} e l s e {

Account o th e r = ( Account ) o ;
i f ( i d != o th e r . i d ) {

r e s u l t = f a l s e ;
} e l s e i f ( name == nu l l && othe r . name != nu l l ) {

r e s u l t = f a l s e ;
} e l s e i f ( name != nu l l && ! name . e qua l s ( o t h e r . name) ) {

r e s u l t = f a l s e ;
}

}
re tu rn r e s u l t ;

}
}

Prologue

Summary
Inheritance allows for the creation of polymorphic methods.
A reference variable of type T can be used to store the reference of objects from the
class T or any of its subclasses.
When a superclass declares an abstract method, it forces the subclasses to provide
an implementation for the method.
A class that declares an abstract method must be abstract.
One cannot create an object from an abstract class.
Object is the most general class in Java.
All the classes inherit directly or indirectly from the class Object.
Object declares the methods equals, toString, getClass, etc.
All objects in Java have a method equals and toString.
Subclasses can override methods.
The name lookup mechanism always starts with the class of the object, not the
compile time type of the reference variable (unless the method is static or final).
Called dynamic or late binding.

66 69

Next module

Generics

67 69

References I

E. B. Koffman and Wolfgang P. A. T.
Data Structures: Abstraction and Design Using Java.
John Wiley & Sons, 3e edition, 2016.

68 69

Marcel Turcotte
Marcel.

School of Electrical Engineering and Computer Science (EECS)
University of Ottawa

69 / 69

Marcel.

Preamble
Overview
Learning objectives
Plan

Polymorphism
Inheritance and Java
Prologue