View
220
Download
0
Embed Size (px)
Citation preview
Inheritance and IS-A• 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– A car made by this factory is an Acura.– ABMISpreadsheet IS-A BMISpreadsheet
• IS-A vs. Inheritance– Human inherits Mammal traits, therefore Human IS-A
Mammal– Inheritance => IS-A but not vice versa
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 "";
} }
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
indexOf(“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
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( )
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
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;…
public AStringHistoryEnumerator (StringHistory theStringHistory){
stringHistory = theStringHistory;}public boolean hasMoreElements () {
…}public String nextElement() {
…}
}
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
Alternative Conventions for Variable-Sized Collection
public interface I {public void add (T t);public T get (int index);
public int size();}
Arbitrary Type.
Read methods
Write method
ObjectEditor understands both
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 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– Properties
• Title, Dept, Number
– Variables:• Title, Dept, Number
• Not appropriate for freshman seminar– Number is not a variable!
Alternative 2: Two Course Classes
• Regular Course – Properties
• Title, Dept, Number
– Variables:• Title, Dept, Number
• Freshman Seminar– Properties
• Title, Dept, Number
– Variables:• Title, Dept
– Constant• 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;}
}
• No super call()!
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 ARegularCourse
package 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;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. Do not need explicit implements clause in subclass if no additional public methods implemented,– public class ARegularCourse extends ACourse { …. }
• Separation of abstract and concrete methods with interfaces.
Abstract methods vs. Interfaces
• Non-public abstract methods relevant even in Java
• All 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;}
}
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.
Old 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;}
}
No init
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;}
}
Polymorphism vs. Overloading and Dynamic Dispatch
• Create polymorphic code when you can– In overloading and dynamic dispatch, multiple implementations associated with each method
name.– In polymorphic case, single implementation.
• Use interfaces rather than classes as types of parameters• Use supertypes rather than subtypes as types of parameters
• Polymorphism vs. Overloading– Polymorphism: single print (Course course)– Overloading: print (ARegularCourse course) and print
(AFreshmanSeminar course) with same implementation.• Polymorphism vs. Dynamic Dispatch
– Polymorphism: single getTitle() in ACourse– Dynamic dispatch: getTitle() in AFreshmanSeminar() and getTitle() in
ARegularCourse() with same implementation.• Cannot always create polymorphic method.
– getNumber() for ARegularCourse and AFreshmanSeminar do different things.– print(Course course) and print (CourseList courseList) do different
things.• When polymorphism not possible try overloading and dynamic dispatch.
Advantages of 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) { 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 );
}
Cannot always get rid of manual dispatch/instanceof
static void print (Course course) { if (course instanceof RegularCourse)
System.out.print(“Regular Course: ”); else if (course instanceof AFreshmanSeminar)
System.out.println(“Freshman Seminar”); System.out.println(
course.getTitle() + " " +course.getDepartment() +course.getNumber() );
}
Cannot always get rid of manual dispatch/instancof
static void print (Course course) { printHeader (course); System.out.println(
course.getTitle() + " " +course.getDepartment() +course.getNumbert() );
}static void printHeader (ARegularCourse course) {
System.out.print(“Regular Course: ”);}static void printHeader (AFreshmanSeminar course) {
System.out.print(“Freshman Seminar: ”);}
At compile time, do not know if regular course or freshman
seminar
Actual parameter cannot be supertype of formal parameter
printHeader() in ARegularCourse
package courses;public class ARegularCourse extends ACourse implements Course {
…public void printHeader () { System.out.print (“Regular Course: ”)
}}
printHeader() in AFreshmanSeminar
package courses;public class AFreshmanSeminar extends ACourse implements FreshmanSeminar {
…public void printHeader () { System.out.print (“Freshman Seminar: ”)
}}
Cannot always get rid of manual dispatch/instancof
• Should not put printHeader() in ARegularCourse or AFreshmanSeminar as it is UI code.• Hence need to use instanceof.• Will use it in parsers
static void print (Course course) { course.printHeader(); System.out.println(
course.getTitle() + " " +course.getDepartment() +course.getNumbert() );
}
Polymorphism vs. Overloading and Dynamic Dispatch
• Create polymorphic code when you can– In overloading and dynamic dispatch, multiple implementations associated with each method
name.– In polymorphic case, single implementation.
• Use interfaces rather than classes as types of parameters• Use supertypes rather than subtypes as types of parameters
• Polymorphism vs. Overloading– Polymorphism: single print (Course course)– Overloading: print (ARegularCourse course) and print
(AFreshmanSeminar course) with same implementation.• Polymorphism vs. Dynamic Dispatch
– Polymorphism: single getTitle() in ACourse– Dynamic dispatch: getTitle() in AFreshmanSeminar() and getTitle() in
ARegularCourse() with same implementation.• Cannot always create polymorphic method.
– getNumber() for ARegularCourse and AFreshmanSeminar do different things.– print(Course course) and print (CourseList courseList) do different
things.• When polymorphism not possible try overloading and dynamic dispatch.
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
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"));
}
Course Input. vs. Title Input Structure
<Title> <Title> <Title>…
<Course> <Course> <Course>…
<String>
Random Thoughts
FSRC<Title><Dept><Number>
<FS><RC>
<Title>
<Dept><String><String>
<String>
<String>
Terminal
Non-Terminal
Grammar
<CourseList> <Course> * <Course> <RC> | <FS><RC> RC <Title> <Dept> <Number><FS> FS <Title> <Dept><Title> <String><Dept> <String>
Production/Rule
LHS RHSAlternation
First
First will be used to decide on alternation
Repetition
English Grammar
<Adjective> <Noun>
little Terminal
<Noun Phrase> <Adjective> <Noun>
<Noun Phrase >
boy
Non Terminal
Grammar-based Concepts• Root: A distinguished non-terminal in the grammar
– E.g. <Course List>, <Noun Phrase>
• Sentence: Any sequence of terminals– E.g.: boy little, little boy
• Legal sentence: A sequence of terminals derived from the root using the grammar rules.– E.g.: little boy
• Legal phrase: A sequence of terminals derived from some non-terminal
• Language: The (possibly infinite) set of legal sentences– E.g. {little boy, big boy, little girl, …}
• Parser: A program that recognizes a language (set of legal sentences), that is, can distinguish between a legal and illegal sentence
Deriving Terminals from a Non-Terminal
• Find a rule in which the non-terminal is the LHS.
• Replace the non-terminal with the RHS.
• If the RHS has no non-terminals, then we are done.
• Otherwise, derive terminals from each of the non-terminals in the RHS.
little
<Noun Phrase> <Adjective> <Noun>
<Noun Phrase >
<Adjective> <Noun>
boy
<Adjective> little
<Noun> boy
Main class: Previous 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: New Main methodpublic class ACourseDisplayer {
public static void main(String[] args) {fillCoursesInteractively();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);
}}
}
Interactive Fillingstatic void fillCoursesInteractively() { System.out.println("Please enter course info, terminating with a period:");
courses = (new ACourseParser()).parseCourseList();}
Processing Course Sequence
package courses;import java.io.DataInputStream;import collections.CourseList;import collections.ACourseList;public class ACourseParser implements CourseParser { //<CourseList> <Course>* public CourseList parseCourseList() { CourseList courseList = new ACourseList(); String nextToken; while (true) {
nextToken = readString(); if (nextToken.equals(".")) break; else
courseList.addElement(parseCourse(nextToken)); } return courseList; }
Return type is LHS of corresponding production
Each time method called prefix of input should be legal phrase derived
from LHS
Processing Course
// <Course> <RC> | <FS>Course parseCourse (String firstToken) {
if (firstToken.toUpperCase().equals("FS")) return parseFreshmanSeminar(); else if (firstToken.toUpperCase().equals("RC")) return parseRegularCourse(); else { return null; }
}
Return type is non-terminal of corresponding production
Processing FreshmanSeminar
//<FS> FS <Title> <Dept>Course parseFreshmanSeminar () {
String title = readString(); String dept = readString(); return new AFreshmanSeminar(title, dept);
}
FS already consumed!Return type is non-terminal of corresponding production
Method consumes, RHS Tokens not
consumed by caller
Processing Regular Course
//<RC> RC <Title> <Dept> <Number>Course parseRegularCourse () {
String title = readString(); String dept = readString(); int number = readInt(); return new ARegularCourse (title, dept, number);
}
Parser Structure• Each production associated with a parser
method.• Parser method returns object associated with
LHS of production.• Usually at start of method execution
– Prefix of unconsumed input should be legal phrase derived from LHS
– Unless calling method consumed one ore more tokens of the phrase to choose an alternative rule
• Such a parser called: recursive descent parser• Illustrates top-down programming