inheritance –inheriting ancestor’s traits –inheriting benefactor’s assets –inheriting...

153
Inheritance • Inheritance – inheriting ancestor’s traits – inheriting benefactor’s assets – inheriting instance members( methods/variables) • IS-A Relationship – human IS-A Mammal – salmon IS-A Fish – “Joe Doe” IS-A Student – ABMISpreadsheet IS-A BMISpreadsheet – ACharHistory IS-A CharHistory

Post on 19-Dec-2015

235 views

Category:

Documents


0 download

TRANSCRIPT

Inheritance• Inheritance

– inheriting ancestor’s traits– inheriting benefactor’s assets– inheriting instance members( methods/variables)

• IS-A Relationship– human IS-A Mammal– salmon IS-A Fish– “Joe Doe” IS-A Student– ABMISpreadsheet IS-A BMISpreadsheet– ACharHistory IS-A CharHistory

Example

String History

public interface StringHistory {

}

public void addElement (String element);

public int size();

public String elementAt (int index);

Implementing the History

public class AStringHistory implements StringHistory { public final int MAX_SIZE = 50; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } public void addElement(String element) { if (isFull())

System.out.println("Adding item to a full history"); else {

contents[size] = element; size++;}

} }

Using the History

public static void main(String[] args) { StringHistory names = new AStringHistory(); while (true) { String input = readLine();

if (input.length > 0) if (input.charAt(0) == 'q') break; else if (input.charAt(0) == 'p' ) print(names);

else names.addElement(input);

}}

Printing a History

static void print(StringHistory strings) { System.out.println("******************"); for ( int elementNum = 0; elementNum < strings.size(); elementNum++)

System.out.println(strings.elementAt(elementNum));}

static String readLine() {try {

return inputStream.readLine();} catch (Exception e) {

System.out.println(e);return "";

} }

Database

Databasepublic interface StringDatabase { //from history

public int size();public void addElement (String element);public String elementAt (int index); //additional methods

}

public boolean member (String element);

public void deleteElement(String element);

public void clear();

deleteElement (String element)

4 James Dean

Joe Doe

Jane Smith

size array

John Smith

deleteElement(“Joe Doe”);

public void deleteElement (String element) { contents[indexOf(element)] = contents[size - 1]; size--;

}John Smith

3

Elements out of order!

deleteElement (String element)

4 James Dean

Joe Doe

Jane Smith

size array

John Smith

deleteElement(“Joe Doe”);

public void deleteElement (String element) { shiftUp(indexOf(element));}

1

index

Multi-element window

4 James Dean

Joe Doe

Jane Smith

size array

John Smith

deleteElement(“Joe Doe”);

public void deleteElement (String element) { shiftUp(indexOf(element));}

Jane Smith

1

index

contents[index] = contents[index + 1];

deleteElement (String element)

4 James Dean

Joe Doe

Jane Smith

size array

John Smith

deleteElement(“Joe Doe”);

public void deleteElement (String element) { shiftUp(indexOf(element));}

Jane Smith

John Smith

3

void shiftUp (int startIndex) { for (int index = startIndex ; index + 1 < size; index++) contents[index] = contents[index + 1]; size--;}

2

index

indexOf (String element)

4 James Dean

Joe Doe

Jane Smith

size array

John Smith

indexOf(“Joe Doe”);

0

index

indexOf (String element)

4 James Dean

Joe Doe

Jane Smith

size array

John Smith

deleteElement(“Joe Doe”);

1

index

public int indexOf (String element) { for ( index = 0; index < size && !element.equals(contents[index];

index++) ;

return index;}

public boolean member(String element)

4 James Dean

Joe Doe

Jane Smith

size array

John Smith

member(“Joe Doe”);

public int indexOf (String element) { for ( index = 0; index < size && !element.equals(contents[index];

index++) ;

return index;}

public boolean member (String element) { }

return indexOf (element) < size;

public void clear()

4 James Dean

Joe Doe

Jane Smith

size array

John Smith

clear()

public void clear() { while ( size > 0)

deleteElement(size -1);}

3210

public void clear()

4 James Dean

Joe Doe

Jane Smith

size array

John Smith

clear()

public void clear() { size = 0;}

0

addElement(“Mary Doe”)

4 Mary Doe

Joe Doe

Jane Smith

size array

John Smith

1

Logical but not Physical Extensions

clear( )

elementAt( )

size( )

member( )

deleteElement( )

addElement( )

StringDatabase

StringHistory

size( )

elementAt( )

addElement( )

IMPLEMENTS

IMPLEMENTS

elementAt( )

member( )

deleteElement( )

indexOf( )

size( )

addElement( )

shiftUp( )

size

contents

MAX_SIZE

AStringDatabase

clear( )

MAX_SIZE

size

contents

size( )

addElement( )

elementAt( )

AStringHistory

isFull( )

Databasepublic interface StringDatabase { //from history

public int size();public void addElement (String element);public String elementAt (int index); //additional methods

}

public void member (String element);

public void deleteElement(String element);

public void clear();

Physical and Logical Extensions

StringHistory

size( )

elementAt( )

addElement( )

EXTENDS

member( )

deleteElement( )String

Database

clear( )

member( )

deleteElement( )

indexOf( )

shiftUp( )

AStringDatabase

clear( )

IMPLEMENTS

IMPLEMENTS

EXTENDSSupertype

Subtype

MAX_SIZE

size

contents

size( )

addElement( )

elementAt( )

AStringHistory

isFull( )

SuperclassSubclass

Extending an Interface

public interface StringDatabase extends StringHistory {

}

public void member (String element);

public void deleteElement(String element);

public void clear();

public interface StringHistory {

}

public void addElement (String element);public int size();

public String elementAt (int index);

extends/ inherits

fromInherited members

Extending a Class

public class AStringDatabase extends AStringHistory implements StringDatabase { public void deleteElement (String element) { … } int indexOf (String element) { … } void shiftUp (int startIndex) { … } public boolean member(String element) { }

public void clear() { } }

Physical and Computer Inheritance

Human

AStringDatabase

PhysicalObject

Animal

Mammal

Primate

AStringHistory String

ObjectImplicit

extension

Regular Accord

Deluxe Accord

Car

Vehicle

StringDatabase

StringHistory

No Explicit Extension

public class AStringHistory implements StringHistory { public final int MAX_SIZE = 50; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } public void addElement(String element) { if (isFull())

System.out.println("Adding item to a full history"); else {

contents[size] = element; size++;}

} }

Equivalent Class Definition

public class AStringHistory extends Object implements StringHistory { public final int MAX_SIZE = 50; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } public void addElement(String element) { if (isFull())

System.out.println("Adding item to a full history"); else {

contents[size] = element; size++;}

} }

Some Methods of Class Object

MAX_SIZE

size

contents

size( )

addElement( )

elementAt( )

member( )

deleteElement( )

indexOf( )

shiftUp( )

AStringDatabase

AStringHistory

EXTENDS

clear( )

isFull( )

Object

EXTENDS

toString( )

equals( )

clone( )

(new AStringHistory()).toString()

(new AStringDatabase()).toString()

(new ACartesianPoint()).toString()

“hello”.toString()

‘h’.toString()

5.toString()

Used by println()

IS-A Relationships

Object

StringHistory AStringHistory String

AStringDatabaseStringDatabase

implements extends

Printing a History

static void print(StringHistory strings) { System.out.println("******************"); for ( int elementNum = 0; elementNum < strings.size(); elementNum++)

System.out.println(strings.elementAt(elementNum));}

AStringHistory Instance

AStringDatabase Instance

AStringHistory IS-A StringHistory

AStringDatabase IS-A AStringHistory

AStringDatabase IS-A StringHistory

Assignment Rules for Primitive Types

• If T1 narrower than T2 (Set of instances of T1 Set of instances of T2)

• Expression of type T1 can be assigned to Variable of type T2

• Expression of type T2 can be assigned to Variable of type T1 with cast.

Assignment Rules for Object Types

• If T1 IS-A T2

• Expression of type T1 can be assigned to Variable of type T2

• Expression of type T2 can be assigned to Variable of type T1 with cast.

IS-A Definition

• Implements: T1 implements T2 => T1 IS-A T2

• Extends: T1 extends T2 => T1 IS-A T2

• Transitive:– T1 IS-A T2– T2 IS-A T3 – => T1 IS-A T3

• Reflexive:– T1 == T2 => T1 IS-A T2

Type Checking Examples

StringHistory stringHistory = new AStringDatabase();

StringDatabase stringDatabase = new AStringHistory();

Getting an Upgrade

Regular Model Requested

ARegularModel myCar = new ADeluxeModel ();

((ADeluxeModel) myCar). setCity(“Raleigh”);

Deluxe Model Assigned

myCar.steer();

Navigation System

myCar. setCity(“Raleigh”);

Getting a Downgrade

Deluxe Model Requested

ADeluxeModel myCar = new ARegularModel ();

Regular Model Assigned

myCar.steer();myCar. setCity(“Raleigh”);

Type Checking Examples

StringHistory stringHistory = new AStringDatabase();

stringHistory.size()

stringDatabase.clear()

((StringDatabase) stringHistory) .clear()

StringDatabase stringDatabase = new AStringHistory();

stringHistory .clear()

Type Checking Examples

Object[] objects = { “Joe Doe”, new AStringDatabase(), new AStringHistory()};

String[] strings = { “Joe Doe”, new Object()};

IS-A & Polymorphism

print (StringHistory stringHistory) { …}

AStringHistory InstanceAStringDatabase Instance

Actual Parameters of different types

IS-A

Database

Set

Overriding Inherited Methods

MAX_SIZE

size

contents

size( )

addElement( )

elementAt( )

member( )

deleteElement( )

indexOf( )

shiftUp( )

AStringDatabase

AStringHistory

EXTENDS

clear( )

isFull( )

Object

EXTENDS

toString( )

equals( )

clone( )

AStringSet

addElement( )

Overriden Method

Overriding Method

Overriding addElement()public void addElement(String element) {

if (isFull()) System.out.println("Adding item to a full history");

else { contents[size] = element; size++;}

}

public void addElement(String element) { if (member(element)) return;

if (isFull()) System.out.println("Adding item to a full history");

else { contents[size] = element; size++;}

}

superpublic void addElement(String element) {

if (isFull()) System.out.println("Adding item to a full history");

else { contents[size] = element; size++;}

}

public void addElement(String element) { if (member(element)) return;

super.addElement(); }

inherited addElement()

Omitting Superpublic void addElement(String element) {

if (isFull()) System.out.println("Adding item to a full history");

else { contents[size] = element; size++;}

}

public void addElement(String element) { if (member(element)) return;

addElement(); }

Recursive call

More Overriding

MAX_SIZE

size

contents

size( )

addElement( )

elementAt( )

member( )

deleteElement( )

indexOf( )

shiftUp( )

AStringDatabase

AStringHistory

EXTENDS

clear( )

isFull( )

Object

EXTENDS

toString( )

equals( )

clone( )

AStringSet

addElement( )

Overriden Method

Overriding Method

toString( )

More Overriding

public String toString() {String retVal = “”;for (int i = 0; i < size; i++)

retVal += “:” + contents[i];return retVal;

}

stringSet.toString() “AStringSet@1eed58”

stringSet.toString() “:James Dean:John Smith”

Main classpublic static void main(String args[]) { StringDatabase names = new AStringDatabase(); while (true) { String input = Keyboard.readLine(); if (!(input.length() == 0))

if (input.charAt(0) == 'q') break;

else if (input.charAt(0) == 'p') print(names); else if (input.charAt(0) == 'd') names.deleteElement(input.substring(2, input.length())); else if (input.charAt(0) == 'm') System.out.println(names.member(input.substring(2, input.length()))); else if (input.charAt(0) == 'c') names.clear(); else names.addElement(input);

} }

Main with Switchpublic static void main(String args[]) { StringDatabase names = new AStringDatabase(); while (true) { String input = Keyboard.readLine(); if (!(input.length() == 0)) if (input.charAt(0) == 'q')

break; else switch (input.charAt(0)) {

case 'p': print(names); break; case 'd': names.deleteElement(input.substring(2, input.length())); break; case 'm': System.out.println(names.member(input.substring(2, input.length()))); break; case 'c': names.clear(); break; default: names.addElement(input);

} }

Breaks out of the loop

Breaks out of the switch

Switch expression

Switch arm

Switch case (value of switch

expressiuon)

Multi-case armspublic static void main(String args[]) { StringDatabase names = new AStringDatabase(); while (true) { String input = Keyboard.readLine(); if (!(input.length() == 0)) if (input.charAt(0) == 'q')

break; else switch (input.charAt(0)) {

case 'p’, ‘P’: print(names); break; case 'd’, ‘D’: names.deleteElement(input.substring(2, input.length())); break; case 'm’, ‘M’: System.out.println(names.member(input.substring(2, input.length()))); break; case 'c’, ‘C’: names.clear(); break; default: names.addElement(input);

} }

Omitting breakpublic static void main(String args[]) { StringDatabase names = new AStringDatabase(); while (true) { String input = Keyboard.readLine(); if (!(input.length() == 0)) if (input.charAt(0) == 'q')

break; else switch (input.charAt(0)) {

case 'p’, ‘P’: print(names); case 'd’, ‘D’: names.deleteElement(input.substring(2, input.length())); case 'm’, ‘M’: System.out.println(names.member(input.substring(2, input.length())));case 'c’, ‘C’: names.clear();default: names.addElement(input);

} }

Illegal Switch

switch (input ){case “print”: print(names); case “clear”: names.clear(); default: names.addElement(input);

}

Type of switch expression must be ordinal type

Ordinal Type

• Values of type are ordered.

• Each value has a unique successor and predecessor

intchar String double

Collections and Enumerations

• So far scanned enumeration fed into collection

• Could enumerate collections

Printing a History

static void print(StringHistory strings) { System.out.println("******************"); for ( int elementNum = 0; elementNum < strings.size(); elementNum++)

System.out.println(strings.elementAt(elementNum));}

static void print(StringHistory strings) { System.out.println("******************"); StringEnumeration stringEnumeration = strings.elements(); while (stringEnumeration.hasMoreElements()) {

System.out.println(stringEnumeration.nextElement()); }}

Modified String History

package collections;import enums.StringEnumeration;public interface StringHistory {

public String elementAt (int index); public void addElement(String element);public int size();public StringEnumeration elements();

}

StringEnumeration

package enums;public interface StringEnumeration{

public String nextElement();public boolean hasMoreElements();

}

Collection Enumerationpackage collections;public class AStringHistoryEnumerator implements enums.StringEnumeration{

StringHistory stringHistory;int nextElementPos = 0;public AStringHistoryEnumerator (StringHistory theStringHistory) {

stringHistory = theStringHistory;}public boolean hasMoreElements () {

return nextElementPos < stringHistory.size();}public String nextElement() {

String retVal = stringHistory.elementAt(nextElementPos);nextElementPos++;return retVal;

}}

Modied AStringHistory

package collections;import enums.StringEnumeration;public class AStringHistory implements StringHistory {

public final int MAX_SIZE = 50;String[] contents = new String[MAX_SIZE];int size = 0;public StringEnumeration elements() {

return new AStringHistoryEnumerator(this);}public int size() {

return size;}…

}

Enumerator/Iterator Design Pattern

StringHistoryAStringHistoryEnumeration

CharHistoryACharHistoryEnumeration

NumberListANumberListEnumeration

CollectionCollection Enumeration

Design Pattern• Inspired by Architectural Pattern• Reusable programming pattern• Not specific class or interface, infinite family of

classes/interfaces• E.g.

– Enumeration

– Scanner pattern

• Language-independent pattern language• Usually involves multiple objects

– Collection and collection enumeration

Design Pattern

• Encyclopaedia of patterns

• Hard to read

• Not taught to undergrad students

• Large project offers opportunity!

Architectural Pattern

• Christopher 79– Each pattern is a three part rule, which

expresses a relation between a certain context, a problem, and a solution.

– Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of a solution to that problem, in such a way that you can use this solution a million times over

Screened-in porch

2nd story porch supported by 1st floor porch columns

Flat (not bay) window

DIFFERENT

No outside stairs to 2nd story

Wide plank siding

SIMILAR

Conventions for Variable-Sized Collection

public interface I {public void addElement (T t);public T elementAt (int index);

public int size();}

Arbitrary Type.

Read methods

Write method

Read Vs Write Methods

• Read Methods– Used to get components of object

– Getter methods

– size(), addElement()

• Write Methods– Used to change components of object

– Setter methods

– addElement(), deleteElement(), replaceElement()

• Distinction independent of Conventions• Conventions used in Object Editor

Java Vectors and Enumerations

• Just like collections we defined

• Except they can store and enumerate arbitrary objects

nullVector Instance

Vectors (java.util.Vector)Vector v;

James Dean

Joe Doe

Point Instance

v = new Vector();v.addElement(“James Dean”)v.addElement(“Joe Doe”)

v.addElement(new ACartesianPoint(5, 5))

Vector Instance

v.addElement(new Vector())

v.addElement(5)

Object

Important Methods of Class Vector

public final int size() public final Object elementAt(int index) public final void addElement(Object obj) public final void setElementAt(Object obj, int index) public final void insertElementAt(Object obj, int index) public final boolean removeElement(Object obj) public final void removeElementAt(int index) public final int indexOf(Object obj) public final Enumeration elements()

Methods of Interface Enumeration (java.util.Enumeration)

public boolean hasMoreElements(); public Object nextElement();

Enumeration elements = vector.elements();while ( elements.hasMoreElements()) System.out.println(elements.nextElement();

Methods of Interface Enumeration (java.util.Enumeration)

public boolean hasMoreElements(); public Object nextElement();

for (Enumeration elements = vector.elements(); elements.hasMoreElements();) System.out.println(elements.nextElement();

String history user

null

Using Vector Directly

Vector v = new Vector();

v.addElemen(”Joe Doe”);

PointModelInstancePointModelInstance

v.removeElementAt(0);

Vector Instance

addElement(): Object void

elementAt(): index Object

removeElementAt(): Object void

v.addElement(“John Smith”);v.addElement(new Vector());

Violating Least Privilege

size(): intVector Instance

String history user

AStringHistory instance

elementAt(): index String

addElement(): String void

size(): int

null

Encapsulating Vector

Vector v = new Vector();

PointModelInstance

StringHistory stringHistory = new AStringHistory()

stringHistory.addElement(“Joe Doe”);stringHistory.addElement(new Vector())

addElement(): Object void

elementAt(): index Object

removeElementAt(): Object void

size(): intVector Instance

Encapsulating Vectorimport java.util.Vector;

public class AStringHistory implements StringHistory {

Vector contents = new Vector();

public void addElement (String s) {

contents.addElement(s);

}

public String elementAt (int index) {

return (String) contents.elementAt(index);

}

public int size() {

return contents.size();

}

}

Simply converts types

Adapter Pattern

• Degree of adaptation undefined.• Methods offered to client

– Adapted name– Adapted type

client adapteeadapter

Access control on variables

  public: accessible in all classes.

   protected: accessible in all subclasses of its class and all classes in its package.

   default: accessible in all classes in its package.

   private: accessible only in its class.

Course Displayer

• User input course title

• Program displays course number, if offered.

Course Displayer User Interface

Course Displayer Classes

• Course List– Matches title

• Main class– Creates course list and adds course instances– Prints courses

• Combines dept and number into one string

• Course classes

Alternative 1: One Course Class

• Course– Variables:

• Title, Dept, Number

– Properties• Title, Dept, Number

• Not appropriate for freshman seminar– Number is not a variable!

Alternative 2: Two Course Classes

• Regular Course – Variables:

• Title, Dept, Number

– Properties• Title, Dept, Number

• Freshman Seminar– Variables:

• Title, Dept

– Constant• Number

– Properties• Title, Dept, Number

• But some variables/properties are common– Title, Dept

Alternative 3: Three Course Classes

• Additional class for common variables– Title, Dept

• Two course classes inherit from it– Regular course adds number variable and

property – Freshman seminar adds number constant and

property

Bottom-up vs. Top-down Inheritance Hierarchy

AStringHistory

AStringSet

AStringDatabase AFreshmanSeminar ARegularCourse

ACourse

Not instantiated

ACourse

• Should not be instantiated

• Cannot have course without a number!

• Always some subclass is instantiated

• Declared as abstract class.

Abstract classes

• Java ensures they are not instantiated

• Abstract vs regular class mammal vs. homo sapiens

ACourse

package courses;public abstract class ACourse {

String title, dept;public ACourse (String theTitle, String theDept) {

title = theTitle;dept = theDept;

}public String getTitle() {

return title;}

public String getDepartment() {return dept;

}}

ARegularCourse

package courses;public class ARegularCourse extends ACourse implements Course {

int courseNum;public ARegularCourse (String theTitle, String theDept, int

theCourseNum) {super (theTitle, theDept);courseNum = theCourseNum;

} public int getNumber() {

return courseNum;}

}

AFreshmanSeminar

package courses;public class AFreshmanSeminar extends ACourse implements FreshmanSeminar {

public AFreshmanSeminar (String theTitle, String theDept) {super (theTitle, theDept);

}public int getNumber() {

return SEMINAR_NUMBER;}

}

Alternative ARegularCoursepackage courses;public class ARegularCourse extends ACourse implements Course {

int courseNum;public ARegularCourse (String theTitle, String theDept, int

theCourseNum) {courseNum = theCourseNum;super (theTitle, theDept);

} public int getNumber() {

return courseNum;}

}

• Super call must be first statement in constructor• Superclass vars initialized before subclass vars• Subclass vars may be assigned expressions

involving superclass vars.• Subclass vars not visible in superclass

Alternative ARegularCoursepackage courses;public class ARegularCourse extends ACourse implements Course {

int courseNum;public ARegularCourse (String theTitle, String theDept, int

theCourseNum) {courseNum = theCourseNum;

} public int getNumber() {

return courseNum;}

}

• Super call must be first statement in constructor• Superclass vars initialized before subclass vars• Subclass vars may be assigned expressions

involving superclass vars.• Subclass vars not visible in superclass

ACourse

package courses;public abstract class ACourse extends Object {

String title, dept;public ACourse (String theTitle, String theDept) {

title = theTitle;dept = theDept;

}public String getTitle() {

return title;}

public String getDepartment() {return dept;

}}

Missing super call

Every class including Object has constructor

Equivalent ACourse

package courses;public abstract class ACourse extends Object {

String title, dept;public ACourse (String theTitle, String theDept) {

super();title = theTitle;dept = theDept;

}public String getTitle() {

return title;}

public String getDepartment() {return dept;

}}

Automatically inserted

Alternative ARegularCoursepackage courses;public class ARegularCourse extends ACourse implements Course {

int courseNum;public ARegularCourse (String theTitle, String theDept, int

theCourseNum) {courseNum = theCourseNum;

} public int getNumber() {

return courseNum;}

}

Equivalent Alternative ARegularCourse

package courses;public class ARegularCourse extends ACourse implements Course {

int courseNum;public ARegularCourse (String theTitle, String theDept, int

theCourseNum) {super();courseNum = theCourseNum;

} public int getNumber() {

return courseNum;}

}

• Java complains superclass does not have parameterless constructor

Course Interface

package courses;public interface Course {

public String getTitle();public String getDepartment();public int getNumber();

}

Freshman Seminar Interface

package courses;public interface FreshmanSeminar extends Course {

public final int SEMINAR_NUMBER = 6;}

CourseList

package collections;import courses.Course;public interface CourseList {

public void addElement(Course element);public Course matchTitle (String theTitle);

}

ACourseListpackage collections;import courses.Course;public class ACourseList implements CourseList {

final int MAX_SIZE = 50;Course[] contents = new Course[MAX_SIZE];int size = 0;public int size() {

return size;}boolean isFull() {

return size == MAX_SIZE;}public void addElement(Course element) {

if (isFull())System.out.println("Adding item to a full collection");

else {contents[size] = element;size++;

}

}

ACourseList

public Course matchTitle (String theTitle) {for (int courseIndex = 0; courseIndex < size; courseIndex++) {

if (contents[courseIndex].getTitle().equals(theTitle))return contents[courseIndex];

}return null;

}

}

Main class: Importspackage main;import courses.Course;import courses.ARegularCourse;import courses.AFreshmanSeminar;import collections.CourseList;import collections.ACourseList;import java.io.BufferedReader;import java.io.InputStreamReader;

Main class: Main methodpublic class ACourseDisplayer {

public static void main(String[] args) {fillCourses();while (true) {

System.out.println("Please enter course title:");String inputLine = readString();if (inputLine.equals("."))

break;Course matchedCourse = courses.matchTitle(inputLine);if (matchedCourse == null)

System.out.println("Sorry, this course is not offered.");

else {printHeader();print (matchedCourse);

}}

}

Main class: Filling List

static CourseList courses = new ACourseList();static void fillCourses() {

courses.addElement(new ARegularCourse ("Intro. Prog.", "COMP", 14));

courses.addElement(new ARegularCourse ("Found. of Prog.", "COMP", 114));

courses.addElement(new AFreshmanSeminar("Comp. Animation", "COMP"));

courses.addElement(new AFreshmanSeminar("Lego Robots", "COMP"));

}

Main class: printing static void printHeader() {

System.out.println ("TITLE " + "NUMBER ");} static void print (Course course) {

System.out.println( course.getTitle() + " " + course.getDepartment() + course.getNumber() );

}

Main class: reading static BufferedReader dataIn = new BufferedReader (new InputStreamReader(System.in));

static String readString() {try {

return dataIn.readLine();} catch (Exception e) {

return null;}

}

Abstract method

• Declared only in abstract classes

• Keyword: abstract

• No body

• Each subclass must implement it

ACourse

package courses;public abstract class ACourse {

String title, dept;public ACourse (String theTitle, String theDept) {

title = theTitle;dept = theDept;

}public String getTitle() {

return title;}

public String getDepartment() {return dept;

}abstract public String getNumber();

}

AFreshmanSeminar and ARegularClass must implement it

Course Interfacepackage courses;public interface Course {

public String getTitle();public String getDepartment();public int getNumber();

}

package courses;public class ARegularCourse extends ACourse implements Course {

int courseNum;public ARegularCourse (String theTitle, String theDept, int

theCourseNum) {super (theTitle, theDept);courseNum = theCourseNum;

} public int getNumber() {

return courseNum;}

}

Abstract methods vs. Interfaces• Public abstract methods subsumed by interfaces

– Useful only in languages such as C++ with no interfaces

• Abstract class can be declared to implement interfaces:public abstract class ACourse implements Course {

…}

• Unimplemented methods become abstract methods to be implemented by concrete subclasses

• Separation of abstract and concrete methods in abstract class.

Abstract methods vs. Interfaces

• Non-public abstract methods relevant even in Java

• Interface methods must be public

• E.g. – abstract boolean isFull() ;

Useful abstract methodspublic abstract class ACollection {

abstract boolean isFull();abstract void uncheckedAddElement(Object element)public void addElement(Object element) {

if (!isFull())uncheckedAddElement(element);

elsehandleError()

}void handleError () {…};

}

Abstract class vs. methods

• Abstract method => containing class abstract– Cannot have an unimplemented method in an

instance

• Abstract class may not contain abstract method

Abstract methods in constructorspublic abstract class ACourse {

String title, dept;public ACourse (String theTitle, String theDept) {

title = theTitle;dept = theDept;// “innocuous” debugging statement added to ACourseSystem.out.println("New course created: " + "Title:" + title + "

Dept:"+ dept + " Number: " + getNumber()) ; } public String getTitle() {

return title;}

public String getDepartment() {return dept;

}abstract public String getNumber(); 

}

Abstract methods in constructors

getNumber() called before subclass constructor has initialized variables

Abstract methods in constructors

• Beware of abstract methods being called in constructors.

• They may access uninitialized variables in subclasses!

Initializing declaration

public class ARegularCourse extends ACourse implements Course {int courseNum = 99;

public ARegularCourse (String theTitle, String theDept, int theCourseNum) {

super (theTitle, theDept);courseNum = theCourseNum;

} public int getNumber() {

return courseNum;}

}

Initializing declarations

Initializations in declarations processed after superclass constructor returns Why correct value?

Constant initializations

• Done when constants allocated memory.

• Shared by all instances.

• When class is loaded in memory.

• Not when an instance created.

Processing of new

  The variables declared in ARegularCourse and Course are allocated space but not initialized.

 The constructor of ARegularCourse is called.

  It calls the constructor of ACourse in its first statement.    

(new ARegularCourse ("Intro. Prog.", "COMP", 14));

Processing of new• The initializations in the declarations of the variables

of ACourse are processed. In this case there no initializations.

  The constructor of ACourse is started.   The two instance variables of ACourse are assigned

parameter values, “Intro. Prog.” And “COMP”.    The values of these variables are printed.    The method getNumber() of ARegularCourse is

called and the default value of courseNum is printed.

Processing of new    The constructor of ACourse returns.    The initializations in the declarations of the

variables of ARegularCourse are processed. In this case, courseNum is assigned the value 0.

   Execution resumes in the constructor of ARegularCourse.

  The courseNum variable is assigned the parameter value, 14.

   The constructor of ARegularCourse returns.    The new statement completes, returning the

new instance to its caller.

Accessing superclass variablespackage courses;public class ARegularCourse extends ACourse

implements Course {int courseNum = 99;

public ARegularCourse (String theTitle, String theDept, int theCourseNum) {

super (theTitle, theDept);courseNum = theCourseNum;title = theTitle;

} public int getNumber() {

return courseNum;}

} Access allowed since in same package

Accessing Superclass variables

package courses;public class AFreshmanSeminar extends ACourse implements FreshmanSeminar {

public AFreshmanSeminar (String theTitle, String theDept) {super (theTitle, theDept);title = theTitle;

}public int getNumber() {

return SEMINAR_NUMBER;}

} Access allowed since in same package

Accessing superclass variablespackage courses;public abstract class ACourse {

String title, dept;public ACourse (String theTitle, String theDept) {

//title = theTitle;dept = theDept;// “innocuous” debugging statement added to ACourseSystem.out.println("New course created: " + "Title:" + title + "

Dept:"+ dept + " Number: " + getNumber()) ; } public String getTitle() {

return title;}

public String getDepartment() {return dept;

}abstract public String getNumber(); 

}

No longer necessary

Accessing superclass variablespublic abstract class ACourse {

String title, dept;public ACourse (String theTitle, String theDept) {

//title = theTitle;dept = theDept;// “innocuous” debugging statement added to ACourseSystem.out.println("New course created: " + "Title:" + title + "

Dept:"+ dept + " Number: " + getNumber()) ; } public String getTitle() {

return title;}

public String getDepartment() {return dept;

}abstract public String getNumber(); 

}

Accessing uninitialized valuepublic abstract class ACourse {

String title, dept;public ACourse (String theTitle, String theDept) {

//title = theTitle;dept = theDept;// “innocuous” debugging statement added to ACourseSystem.out.println("New course created: " + "Title:" + title + "

Dept:"+ dept + " Number: " + getNumber()) ; } public String getTitle() {

return title;}

public String getDepartment() {return dept;

}abstract public String getNumber(); 

}

accesses uninitialized value

accesses initialized value

Redeclaring Superclass variables

package courses;public class AFreshmanSeminar extends ACourse implements FreshmanSeminar {

String title;public AFreshmanSeminar (String theTitle, String theDept) {

super (theTitle, theDept);title = theTitle;

}public int getNumber() {

return SEMINAR_NUMBER;}

}Refers to

overriding variable.

Overriding of variables legal in Java!

Redeclaring superclass variables

public class ARegularCourse extends ACourse implements Course {int courseNum = 99;

String title;public ARegularCourse (String theTitle, String

theDept, int theCourseNum) { super (theTitle, theDept);courseNum = theCourseNum;title = theTitle;

} public int getNumber() {

return courseNum;}

}

Redeclaring superclass variables

Accessing uninitialized valuespublic abstract class ACourse {

String title, dept;public ACourse (String theTitle, String theDept) {

//title = theTitle;dept = theDept;// “innocuous” debugging statement added to ACourseSystem.out.println("New course created: " + "Title:" + title + "

Dept:"+ dept + " Number: " + getNumber()) ; } public String getTitle() {

return title;}

public String getDepartment() {return dept;

}abstract public String getNumber(); 

}

accesses uninitialized value

accesses uninitialized value

Re-declaring subclass variables

• Happens accidentally when class if factored.

• Original variable in subclass remains.

• Beware!

Multiple Constructorspackage courses;public abstract class ACourse {

final String DEFAULT_DEPT = “COMP”;final String DEFAULT_TITLE = “Topics in Computer Science”;String dept, title; public ACourse (String theTitle, String theDept) {

title = theTitle;dept = theDept;System.out.println("New course created: " + "Title:" + title + " Dept:"+

dept + " Number: " + getNumber()) ; }

public ACourse () { dept = DEFAULT_DEPT; title = DEFAULT_TITLE; System.out.println("New course created: " + "Title:" + title + " Dept:"+

dept + " Number: " + getNumber()) ;}

public String getTitle() {return title;} public String getDepartment() {return dept}; abstract public String getNumber(); }

Multiple Constructors

package courses;public class AFreshmanSeminar extends ACourse implements FreshmanSeminar {

public AFreshmanSeminar (String theTitle, String theDept) {super (theTitle, theDept);

}public AFreshmanSeminar () {}public int getNumber() {

return SEMINAR_NUMBER;}

}new AFreshmanSeminar (“Lego Robots”, “COMP”);

new AFreshmanSeminar();

Removing Code Duplicationpackage courses;public abstract class ACourse {

final String DEFAULT_DEPT = “COMP”;final String DEFAULT_TITLE = “Topics in Computer Science”;String dept, title; public ACourse (String theTitle, String theDept) {

title = theTitle;dept = theDept;System.out.println("New course created: " + "Title:" + title + " Dept:"+

dept + " Number: " + getNumber()) ; }

public ACourse () { dept = DEFAULT_DEPT; title = DEFAULT_TITLE; System.out.println("New course created: " + "Title:" + title + " Dept:"+

dept + " Number: " + getNumber()) ;}

public String getTitle() {return title;} public String getDepartment() {return dept};

abstract public String getNumber(); }

Init methodpackage courses;public abstract class ACourse {

final String DEFAULT_DEPT = “COMP”;final String DEFAULT_TITLE = “Topics in Computer Science”;String dept, title;

public ACourse (String theTitle, String theDept) {init (theTitle, theDept);}public ACourse () { init (DEFAULT_TITLE, DEFAULT_DEPT );}

void init (String theTitle, String theDept) {title = theTitle;dept = theDept;System.out.println("New course created: " + "Title:" + title + " Dept:"+

dept + " Number: " + getNumber()) ; } public String getTitle() {return title;} public String getDepartment() {return dept};

abstract public String getNumber(); }

Calling constructor in same classpackage courses;public abstract class ACourse {

final String DEFAULT_TITLE = “Topics in Computer Science”;

final String DEFAULT_DEPT = “COMP”; String title, dept;

public ACourse (String theTitle, String theDept) {title = theTitle;dept = theDept;System.out.println("New course created: " + "Title:" + title + "

Dept:"+ dept + " Number: " + getNumber()) ; }

public ACourse () { this (DEFAULT_TITLE, DEFAULT_DEPT);

} public String getTitle() {return title;} public String getDepartment() {return dept};

abstract public String getNumber(); }

Java complains parameter may

not be initialized

Calling constructor in same classpackage courses;public abstract class ACourse {

final String DEFAULT_TITLE = “Topics in Computer Science”;

final String DEFAULT_DEPT = “COMP”; String title, dept;

public ACourse (String theTitle, String theDept) {title = theTitle;dept = theDept;System.out.println("New course created: " + "Title:" + title + "

Dept:"+ dept + " Number: " + getNumber()) ; }

public ACourse () {

this (“Topics in Computer Science”, “COMP”;);}

public String getTitle() {return title;} public String getDepartment() {return dept};

abstract public String getNumber(); }

No complaints

Calling constructor in same classpackage courses;public abstract class ACourse {

String tite = “Topics in Computer Science”;;

String dept = “COMP”; public ACourse (String theTitle, String theDept) {

title = theTitle;dept = theDept;System.out.println("New course created: " + "Title:" + title + "

Dept:"+ dept + " Number: " + getNumber()) ; }

public ACourse () { this (title, dept);

} public String getTitle() {return title;} public String getDepartment() {return dept};

abstract public String getNumber(); }

Valid complaint that title and dept may not be initialized correctly

as superclass constructor not called

Calling constructor in same classpackage courses;public abstract class ACourse {

String tite = “Topics in Computer Science”;;

String dept = “COMP”; public ACourse (String theTitle, String theDept) {

title = theTitle;dept = theDept;this();

}public ACourse () {

System.out.println("New course created: " + "Title:" + title + " Dept:"+ dept + " Number: " + getNumber());}

public String getTitle() {return title;} public String getDepartment() {return dept};

abstract public String getNumber(); }

Java complains that this() must be first call

Possible constructor call semantics

• Rule so far: each constructor calls superclass constructor.

• Problem: then super class initialized multiple times.– Not a problem if each initialization yields the

same result.– Can have multiple constructors doing different

initializations.– Same constructor may do different things on

different invocations or may have side effects.

Actual Semantics• A constructor may call another constructor as first

statement.• Super not called in that case.• Only last call in constructor chain calls super.• Hence no danger of super being initialized multiple

times.• But danger that constructor parameters may be

uninitialized.• Literal parameters ok.• Constructor call must be first statement.• Otherwise code executed before superclass

initialized

Init methods

• Allows initialization after object is created.

• Initializer can be different from creator

• Init methods can be in interfaces

• Init method(s) recommended but not required

Allowing init after constructionpackage courses;public abstract class ACourse {

String title = “Topics in Computer Science”;;

String dept = “COMP”; public ACourse (String theTitle, String theDept) {

init(theTitle, theDept);}

public void init (String theTitle, String theDept) {title = theTitle;dept = theDept;

}public ACourse () { }

public String getTitle() {return title;} public String getDepartment() {return dept};

abstract public String getNumber(); }

Should go in interface.

Uses default values

Default values.

ARegularCoursepublic class ARegularCourse extends ACourse

implements Course {int courseNum = 99;

public ARegularCourse (String theTitle, String theDept, int theCourseNum) {

super (theTitle, theDept);courseNum = theCourseNum;

} public int getNumber() {

return courseNum;}

}

init in ARegularCoursepublic class ARegularCourse extends ACourse implements

Course {int courseNum = 99;

public ARegularCourse (String theTitle, String theDept, int theCourseNum) {

init (theTitle, theDept, theCourseNum);} public ARegularCourse() {}

public void init (String theTitle, String theDept, int theCourseNum) {

courseNum = theCourseNum;} public int getNumber() {

return courseNum;}

}

No super call

init in ARegularCoursepublic class ARegularCourse extends ACourse implements Course {

int courseNum = 99;

public ARegularCourse (String theTitle, String theDept, int theCourseNum) {

init (theTitle, theDept, theCourseNum);

}

public ARegularCourse() {

}

public void init (String theTitle, String theDept, int theCourseNum) {

super.init(theTitle, theDept);

courseNum = theCourseNum;

}

public int getNumber() {

return courseNum;

}

}

Two ways to construct

• Initialized construction– new ARegularCourse (“Intro. Prog”, “COMP”,

14);

• Construction and then initialization– (new ARegularCourse()).init(“Intro Prog.”,

“COMP”, 14)

Parameterized Constructors

• So far, one parameterized constructor in a class, that initializes all instance variables

• Can create multiple parameterized constructors– To initializes some subset of instance variables.– Use default values assigned by initializing declarations

for the rest.public ACourse (String theTitle) {

title = theTitle;

}

• Add an init method for each parameterized constructor

Overloading, Polymorphism, and Dynamic dispatch

• Same method name works on different types.• Overloading

– Multiple (static or instance) methods with same name but different parameter types.

– Resolved at compile time based on parameter types

• Polymorphism– Same method implementation works on multiple object

types.

• Dynamic dispatch (or virtual methods)– Multiple instance methods with same name in different

classes

– Resolved at execution time based on type of target object

Overloading, Polymorphism, and Dynamic dispatch

static void print (Course course) {System.out.println(

course.getTitle() + " " + course.getDepartment() + course.getNumber() );

}

static void print (CourseList courseList) {…print(course);…

}Overloaded method

Dynamically dispatched method

getNumber() in ARegularCouse

getNumber() in AFreshmanSeminar

ARegularCourse

AFreshmanSeminar

Polymorphic method

getNumber in ARegularCourse

package courses;public class ARegularCourse extends ACourse implements Course {

int courseNum;public ARegularCourse (String theTitle, String theDept, int

theCourseNum) {super (theTitle, theDept);courseNum = theCourseNum;

} public int getNumber() {

return courseNum;}

}

getNumber() in AFreshmanSeminar

package courses;public class AFreshmanSeminar extends ACourse implements FreshmanSeminar {

public AFreshmanSeminar (String theTitle, String theDept) {super (theTitle, theDept);

}public int getNumber() {

return SEMINAR_NUMBER;}

}

Advantages of Overloading/Polymorphism/Dynamic Dispatch

• Easy to understand and program• Avoid manual dispatch /instanceof operator.

– More work– Must update code as subtypes added

static void print (Course course) {int number;if (course instanceof ARegularCourse)

number = ((ARegularCourse)course).getCourseNumberRegularCourse (); else if (course instanceof AFreshmanSeminar)

number = ((AFreshmanSeminar)course).getCourseNumberFreshmanSeminar ();

System.out.println(course.getTitle() + " " +course.getDepartment() + number );

}

Polymorphism vs. Overloading/dynamic dispatch

• Polymorphism offers additional benefit of reuse• Create polymorphic methods whenever possible

– Use interfaces rather than classes as types of parameters– Use supertypes rather than subtypes as types of parameters– print(Course) vs. (print (AFreshmanCourse),

print(ARegularCourse))– Course.getDepartment() vs. (AFreshmanCourse.getDepartment(),

ARegualarCourse.getDepartment())

• No always possible– print(Course) vs. print (CourseList)– AFreshmanCourse.getCourseNumber vs.

ARegularCourse.getCourseNumber()

Overloading vs. dynamic dispatch• Overloading:

– Object is parameter

• Dynamic dispatch:– Object is target

• Method in object class vs. external class– Program decomposition issue– print(Course), print (CourseList) definitions overloaded– AFreshmanSeminar.getCourseNumber(),

ARegularCourse.getCourseNumber() dynamically dispatched

• Overload resolution looks at multiple parameter types– More general and used for that reason also

• Dynamic dispatch is done at runtime– Can be used for that reason