Title: One Way Assignment
1One Way Assignment
- You can assign a subclass (derived) to a
superclass (base), but not the other way around - Object o new String() // This is okay
- String s new Object() // Error
- The subclass has more methods than the superclass
- We could could send toString messages to
instances of both objects, but odoes not know
about toUpperCase - Therefore, an Object should not be treated as a
String - But a String is an Object with extra methods
- You can also pass a subclass object to a
parameter that is a class higher up the
inheritance hierarchy
2Therefore, you can assign anything to an Object
object
- public class TestObject
- public static void main(String args)
- Object object new Object4
- object0 new BankAccount("Devon", 333.45)
- object1 new TextReader()
- object2 new Book("QA76.1", "Comp Fun",
"Rick") - object3 new Borrower()
- for(int j 0 j lt object.length j)
- System.out.println(objectj)
-
-
- Output
- Devon 333.45
- TextReader_at_f92de4bd
- QA76.1, Comp Fun, Rick
- Borrower_at_fb11e4bd
Can you send a withdraw message to each in the
for loop?
3Polymorphism
- All Objects in the preceding code extend Object
- So what happens when you send a message to an
object in an inheritance hierarchy? - The class checks if it has a method with exactly
the same parameters -- and invokes it if it does
have it. - If not, the parent class becomes responsible for
finding the method and invoking it, this
continues up to Object - This would never have begun if the method did not
exist, Why? - You just saw 4 toString messages, how many
methods executed?
4Polymorphism
- Polymorphism comes in several forms
- ad-hoc polymorphism no inheritance required
- Overloading method names println(int) or
println(String) - Overload operators 32 or "3""2"
- real polymorphism inheritance or interfaces
required - the actual method called is not decided at
compiletime - at runtime, the system will decide which method
will be called - late binding
- this is why we say 'send a message' rather than
'call a function' - you do not always know which function (method)
will be called
5Casting
- You can cast some primitive types to another
- double aNumber 1.99
- int anInt (int)aNumber
- You can also cast some types of object to another
- BankAccount anAcct (BankAccount)object0
- Every Java reference variable knows the type of
object it refers to, so object0 has a reference
to a BankAccount - the cast was allowed, but ..
What is the value of anInt?
6You will see class cast exceptions
- ... you can not cast a Book into a BankAccount
- BankAccount anAcct (BankAccount)object2
- However, you can ask a reference variable if it
is an instance of a particular class - use the keyword instanceof
-
java.lang.ClassCastException Book at
TestObject.main(TestObject.java11)
7Recall previous code that sent toString messages
to all objects
- This for loop asks every one of those object if
it is an instance of the BankAccount class - BankAccount messages are only sent if it is a
BankAccount - for(int j 0 j lt object.length j)
- if(objectj instanceof BankAccount)
- BankAccount ref (BankAccount)objectj
- ref.withdraw(233.45)
- System.out.println(ref)
-
-
- Output
- Devon 100.00
8Abstract classes
- If you declare an class as abstract, you can not
instantiate it - makes your design clear
- do not construct a Lendable or a Fruit
- do construct a Book or an Apple
- If you declare a method abstract, you must
declare the class as abstract also - the abstract method heading promises descendants
will implement the method. this makes your design
clear - the compiler complain if you forget
9Protected Access
- Use protected to grant access to a derived class
- can make instance variables protected so all
descendants can access them directly - but don't
do this - protected methods can be used by any object newed
from the hierarchy
10Preventing Inheritance
- You can prevent anyone from extending your class
- make the class final
- final class Manager
- You can prevent anyone from overriding your
method - make the method final
- final public void getDueDate()
11Visibility rules
- private data are not accessible from the subclass
- can add getters and setters to the superclass
- or make the instance variables protected
- Subclasses can then modify/access the common data
- public abstract class Shape extends Object
- private Point upperLeft
- public Shape(Point p)
- upperLeft p
-
- public Point getUpperLeftCorner()
- return upperLeft
-
- public void setUpperLeftCorner(Point p)
- upperLeft p
-
-
12Extend shape, add instance var, add constructor
- public class Circle extends Shape
-
- private double my_radius
- public Circle(Point upperLeft, double radius)
-
- super(upperLeft) // call Shape's constr.
- my_radius radius
-
13The Constructor and Super
- A subclass typically defines its constructor
- If not, you will still get a default constructor
- zero parameters
- it automatically calls the base class constructor
- this constructs the base class and initializes
the data - we can explicitly call the base class by writing
super()which may also pass along arguments - if used, super must be the first message in the
constructor of the derived classes - A derived class overrides a base class by
- adding a method to derived with the same signature
14Abstract classes
- A method is either
- invariant over the hierarchy declare it final
- or changed by in derived class by overriding
- rewrite method heading, do different things
between - A third option Abstract methods
- the method must be given meaning in each and
every derived class - the method is declared abstract in the base
- the listings show an abstract method
15Abstract methods
- Why abstract classes?
- Because the method represents the common behavior
of all classes in the hierarchy - Each class will then be required to implement
that method. - When a class has one or more abstract methods, it
is called an abstract class - An abstract class is never instantiated
- Enough of the abstract, let's get concrete
- check out this new system
16A New SystemFind the Objects
- Your are asked to implement a system that
supports a small set of library operations. The
librarian allows a student to borrow certain
items, return those borrowed items, and pay fees.
Late fees and due dates have been established at
the following rates Late
fee
Length of Borrowbooks 0.50 per
day 14
days - videos 5.00 plus 1.50 each additional day
2 days CDs 2.50 per day
7 daysThe due date is set
when the borrowed item is checked out. A student
with three (3) borrowed items, one overdue item,
or late fees greater than 25.00 may not borrow
anything new. This system must support undo and
redo for book borrows, book returns, and payment
of late fees. The system must have a graphical
user interface.
17Candidate Objects
- Object to represent the model a solution after
eliminating some possibilities - Librarian
- Student
- Book
- Video
- CD
- 3 borrowed books
18Some of these things are similar with a few
differences
19What do books, videos, and CD-Roms have in common?
- Common operations and data perhaps
- know due date
- compute due date
- determine late fee
- know borrower
- check self out
- check self in
20An inheritance hierarchy
The abstract class never instantiated
three concrete classes
21Why not have just one class?
- Some of the behavior differs
- determine due date (2, 7, or 14 days)
- Compute late fee
- Data differs
- books have ISBNs
- videos may have a Hollywood studio name
- Inheritance
- allows you to share implementations
- allows one change in a common method to affect
all - Can add new lendable types later more easily
22Up First, the abstract class
23Designing Java Class Definitions
- public abstract class Lendable // rough first
draft - private data // Common Data
- constructor(s) // Initialize Common Data
- // methods common to all, make these final
- public double getLateFee() ...
- // add methods that each sublcass must
- // implement differently. make these abstract
24Some of the many things a subclass van do
- A subclass can
- add new methods
- add new data fields
- override methods defined in an ancestor
- define its own constructor
- call the super class constructor with super
- call a method in the super class with
super.message
25Abstract methods
- Derived classes differ setDueDate getLateFee
- so make them Abstract, this means the derived
classes must implement them in their own way
more later - public abstract class Lendable // second draft
- private data // TBA
- constructor(s) // TBA
- public double getLateFee() ...
- public boolean isAvailable() ...
- public void checkSelfIn() ...
- public void checkSelfOut(String borrowerID,
- int daysAhead) ...
- // some subclass must implement these two
- abstract public void checkOut()
- abstract public double getLateFee()
26A SubClass
- public class Book extends Lendable
-
- additional private data // TBA
- constructor(s) // TBA
- additional Methods // TBA
- public Book(String CallNum, String Author,
- String title)
- public void checkOut()
- // could call super.checkSelfOut(ID, 14)
- public double getLateFee()
27Some common data fields
- Every class must have a DueDate
- Add my_dueDate my_ID field to the base class
- Since these fields should be private
- add accessors getDueDate and getLendableID
- BTW What do we do about a Date class?
- Java's Date class has been deprecated
- Use Cay's Day class
- Use GregorianCalendar
- Use Rick's DayCounter class
- Make up your own Day class
28Assume we have this DayCounter class
- // The default constructor sets this DayCounter
object // to represent the current date of the
computer clock - public DayCounter()
- // Use this if you want a calendar date to
represent - // a past (argument is negative) or future date.
- public void adjustDaysBy(int days)
29Some common data fields
- Every class in the hierarchy will have these
instance variables of class Lendable - Note subclasses can not directly reference these
- private String my_callNumber
- private String my_title
- private boolean my_availability
- private String my_borrowerID
- private DayCounter my_dueDate
30Lendable's constructor
- // Constructor needs a callNumber. Title was
- // added since it seems that all Lendables will
- // have a title of some sort. These come from
- // the subclasses constructor.
- public Lendable(String callNumber,
- String initTitle)
-
- my_callNumber callNumber // from subclass
- my_title initTitle // from subclass
- // Initialize others in a special way
- my_borrowerID null
- my_dueDate null
- my_availability true
31A few Lendable accessors
- public String getCallNumber()
-
- return my_callNumber
-
- public String getTitle()
-
- return my_title
-
- public boolean isAvailable()
-
- return my_availability
-
- public DayCounter getDueDate()
- return my_dueDate
32Reusing DayCounterEarlier project or in the
Chapter10 folder
- public int daysLate()
- // return a positive of my_dueDate is before
today - DayCounter today new DayCounter()
- return my_dueDate.daysFrom(today)
-
- public boolean isOverdue()
-
- if(this.isAvailable())
- return false // not even checked out
- // Or check to see if this Lendable is overdue
- DayCounter today new DayCounter()
- // Return true if today is greater than
- // the due date for this Lendable
- return daysLate() gt 0
33A Modifying Method in Lendable
- public boolean checkSelfIn()
-
- if(this.isAvailable())
- // this can not be checked out
- return false
-
- else
- // Adjust state so this is checked out
- my_dueDate null
- my_availability true
- return true
-
34checkSelfOut responsibility is split between
Lendable and it subclasses
- protected // called from a subclass checkSelfOut
- void checkOutAnyLendable(String borrowerID,
- int borrowLength )
-
- // Record who is borrowing this Lendable
- my_borrowerID borrowerID
-
- // Set the due date
- my_dueDate new DayCounter() // today's date
- my_dueDate.adjustDaysBy(borrowLength)
-
- // Mark this as no longer available
- my_availability false
35Protected
- The protected access mode means that subclasses
inherit this method (inherit all public
protected elements). - It's invoked by the subclass's checkSelfOut
method. - So far, good design for the following reasons
- subclasses can't change the private variables of
the superclass, even though the subclass has them - doesn't require a bunch of setter methods in
Lendable for subclasses to modify its own
instance variables - the common behavior is in the superclass
- the same thing is done for all subclasses
- We'll get a polymorphic checkSelfOut message
36Abstract methods
- Subclasses differ setDueDate getLateFee
- declare the appropriate methods abstract, to
force sub-classes to implement them in their own
appropriate ways - public abstract class Lendable
- //Don't really borrow a Lendable or eat a Fruit
- ...
- // Subclass must implement these two methods
- abstract public void checkSelfOut(String ID)
- abstract public double getLateFee()
- // Done with Lendable for now
37The Constructor and Super
- A subclass typically defines its constructor.
- If not, you will still get a default constructor
- zero parameters
- it automatically calls the base class constructor
- Constructors in a subclass typically call the
superclass constructor to initialize the objects. - Access superclass with the keyword super
- can pass along arguments super(callNum, title)
- if used, super must be the first message in the
constructor of the derived classes
38So let's extend Lendable
- public class Book extends Lendable
-
- public static final int DAYS_TO_BORROW_BOOK
14 - public static final double BOOK_LATE_DAY_FEE
0.50 - // A new instance variable added to the 5
inherited - private String my_author
- // Can finally construct something
- public Book(String callNumber, String title,
- String author)
- super(callNumber, title) // Lendable
constructor - my_author author
-
- public String getAuthor()
- return my_author
-
- // incomplete, but let's see if something works
39Implement the other abstract methods to do
nothing, then these messages can call Lendable's
methods
- import junit.framework.TestCase
- public class TestBook extends TestCase
-
- public void testGetters()
-
- Book aBook new Book("QA76.1", "C", "Jo")
- assertTrue(aBook.isAvailable())
- assertFalse(aBook.isOverdue())
- assertNull(aBook.getBorrowerID())
- assertEquals("QA76.1", aBook.getCallNumber())
- assertEquals("C", aBook.getTitle()) // C
- assertEquals("Jo", aBook.getAuthor()) //
Rick -
40Test Late fee
- Book overdue
- new Book("Q", "Overdue", "Late fee 30
0.50") - overdue.checkSelfOut("Kim")
- DayCounter dueDate new DayCounter()
- dueDate.adjustDaysBy(Book.DAYS_TO_BORROW_BOOK)
- assertTrue(dueDate.daysFrom(overdue.getDueDate())
0) - assertFalse(overdue.isOverdue())
- assertEquals(0.00, overdue.getLateFee(), 1e-12)
- DayCounter thirtyDaysAgo new DayCounter()
- thirtyDaysAgo.adjustDaysBy(-30)
- overdue.setDueDate(thirtyDaysAgo)
- assertTrue(overdue.isOverdue())
- assertEquals(15.00, overdue.getLateFee(), 1e-12)
41Complete both required methods
- checkSelfOut delegates some work to Lendable and
passes along the unique information borrow length - / Modify the state of this object so it is
borrowed. - _at_param borrowerID The identification of
borrower. - /
- public void checkSelfOut(String borrowerID )
-
- checkOutAnyLendable(borrowerID,
- Book.DAYS_TO_BORROW_BOOK)
-
42getLateFee differs among the different Lendables
- public double getLateFee()
-
- if(this.isAvailable()) // Not even checked out!
- return 0.00
- else
- // A positive daysLate means due date has
passed - int daysOverdue this.daysLate()
- if(daysOverdue gt 0) // This Lendable is
overdue - return daysOverdue Book.BOOK_LATE_DAY_FEE
- else
- return 0.00 // The due date is in the
future -
-