Upcast and Dynamic Binding
Download
Report
Transcript Upcast and Dynamic Binding
The Basics of ObjectOriented Programming
Eric Jui-Lin Lu, Ph.D.
Department of Management Information
Systems
National Chung Hsing University
Object-Oriented Programming
物件導向程式設計(object-oriented programming)
是一種以物件為核心的程式設計方式,這一類的
程式會利用一個或者一個以上的物件來完成工作。
這一類程式設計的一項重點就是找出所需要的物件
當需要一個以上的物件來完成一個工作時,這些物件
之間會互相呼叫(也稱之為傳送訊息,send message)
來互動
Object (or entity, instance)
也就是物件、實體。
例如:汽車、人、表單等等
2
Objects
每一個物件都擁有特性(一般稱之為屬性 attribute)
以及行為(一般稱之為 method 或者 function)
例如:描述汽車的方式有廠牌、排氣量、顏色等,汽
車的行為有加速、煞車等
例如:描述學生的方式有姓名、學號、系別、年級、
連絡住址、身高、體重等,學生的行為有選課、更改
住址等
每一個物件的特性值說明該物件的狀態
我的汽車是 Honda,1600cc,灰色的轎車
資管系周潔輪今年是二年級,他的學號是 11223344。
3
Classes
從一個實體中萃取出我們有興趣的特性以及行為的過程,
我們稱之為抽象化(abstraction)
以學生為例,如果我們今天要完成的系統是保健室的登錄系統,
那麼我們需要從學生萃取出來的特色應該有姓名、學號、身高、
和體重。可是如果要完成的系統是學生選課系統,那麼我們不會
對身高和體重有興趣,自然不需要把這些特色定義出來。
我們需要對每一個物件都進行定義嗎?
以一個有一萬多人的學校,要為每一個學生物件都進行定義的話,
這是非常耗時的。
其實,以一個特定系統而言(例如之前所說的選課系統),每一
個學生物件的特色以及行為都是相同的。如果為每一個學生物件
都定義的話,幾乎都是重複的。
因此,同一類的物件的特色以及行為的定義就統一的定義在類別
(class)裡。
4
Object-Oriented Model
要使用物件來完成工作以前,類別必須先被定義
出來。
在寫物件導向程式的時候,
一般來說,會建議使用現成的類別。在 Java 的套件中,
已經擁有數千個類別的定義。
如果現成的類別不存在,我們就自己定義類別。
因此,Java 的每一個程式都是一個類別
在 Java 的程式中,我們最少需要一個類別,這個
類別控制整個程式的流程,例如先取得使用者的
輸入,利用物件完成工作,最後把結果呈現出來。
這個類別也因此稱之為控制類別(control class)。
5
Hello World
// class 是表明類別的保留字
class HelloWorld {
public static void main(String[] args) {
// System 是 JDK 提供的類別
// System.out 是代表一個物件,也就是標準輸出
System.out.println(“Hello World”);
}
}
6
Use of Date Class
// 將系統時間顯示出來
// 利用一個現成的物件 System.out,以及產生一個新的物件 d
// 利用物件之間的互動,將工作完成
class DisplayDate {
public static void main(String[] args) {
java.util.Date d = new java.util.Date();
System.out.println(d.toString());
}
}
7
An Example
A worker is paid at the hourly rate of $8 per hour for
the first 35 hours worked. Overtime is paid at 1.5 times
the hourly rate for the next 25 hours worked and paid
at 2 times the hourly rate for additional hours worked.
Write a program to input the number of hours worked;
then calculate and output the total amount paid.
物件是什麼?
描述這個物件的屬性是什麼?
這個物件的行為是什麼?
8
Object-Oriented Model
開始定義這個物件的類別。這個類別,我們一
般稱之為模式類別(model class)。
產生一個控制類別,在這個控制類別中,我們
取得使用者輸入的資料,然後產生一個物件
(也就是產生一個之前定義的模式類別的一個
instance),並設定這個物件的值之後,要求物
件計算出薪資總額。
因為要用到 Input 以及 Output,我們也可以使用
JDK 提供的 IO 類別,這一類的類別也稱之為 View
Class.
9
Object-Oriented Model
JDK 提供的 IO classes 有
JOptionPane
String s = JOptionPane.showInputDialog(“Enter Hours”);
JOptionPane.showMessageDialog(null, “Hello World”);
I/O Streams (java.io.*)
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
String s = br.readLine();
java.util.Scanner(JDK 1.5 or above)
Scanner reader = new Scanner(System.in);
int h = reader.nextInt();
這種將類別分成三個主要種類的模式,我們稱
之為 MVC (Model, View, and Control) Model.
10
Instances vs. Classes
Constructor (建構元)
hourly rate, 1.5, and 2 怎麼辦?
instance data
class data(加上 static)
其差別在於
記憶體的考量
instance data 必須物件存在的時候,他才存在;而 class data
是 class 存在的時候,他就存在了。
類似的情形也存在於 method
instance method
class method (加上 static)
11
Encapsulation
物件導向模式的第一個特性 -- Encapsulation
(封裝)
為什麼要 encapsulation?
Java 如何完成 encapsulation?
public
private
protected
none
看一下 UML 的 Class 以及 Object 的圖
12
An Exercise
範例
A company has four salespeople who sell five different
products. Once a day, each salesperson passes in a slip
for each different type of product sold. Each slip
contains
the salesperson number (1 to 4),
the product number (1 to 5), and
the total dollar value of that product sold that day.
Thus, each salesperson passes in between 0 and 5 sales
slips per day. Please write an OO program (not applet)
that will read all information and summarize the total
sales by salesperson.
13
Discussions
討論的主題
有哪些 Model classes?
陣列 vs. Vector
為什麼 Vector 的元素可以包含我們建立的 classes?想想看一個
物件有時候它是某個資料型態,在另一個時候它又是另一個資
料型態。這種特色稱之為多型(Polymorphism),而要了解多
型,就必須先知道繼承(Inheritance)。
Encapsulation、Inheritance、以及 Polymorphism 合
稱物件導向模式的三大特色
注意,有非常多的專家學者強調不要為了符合這三大
特色而犧牲了 reusability 和 maintainability
14
Inheritance
15
Inheritance
Superclasses vs. subclasses
子類別的物件自動繼承父類別的特性(包含屬性
以及行為)
base classes vs. derived classes
protected, private, and public(避免把問題複雜化了,自
己去了解 none 在繼承架構所扮演的角色)
產生繼承架構的方式
specialization
generalization
16
Example
常見的範例:圓形以及矩形。
如何定義一個圓形、矩形。
17
Example
public class Point {
protected int x, y; // coordinates of the Point
public Point() { setPoint( 0, 0 ); }
public Point( int a, int b ) { setPoint( a, b ); }
public void setPoint( int a, int b ) { x = a; y = b; }
public int getX() { return x; }
public int getY() { return y; }
public String toString() {
return "[" + x + ", " + y + "]"; }
}
18
Example
public class Circle extends Point {
protected double radius;
public Circle() {
// implicitly call superclass's constructor occurs here
setRadius( 0 ); }
public Circle( double r, int a, int b ) { super( a, b ); setRadius( r ); }
public void setRadius( double r ) { radius = ( r >= 0.0 ? r : 0.0 ); }
public double getRadius() { return radius; }
// 新增:Calculate area of Circle
public double area() { return Math.PI * radius * radius; }
// 1. 改寫:convert the Circle to a String
// 2. 存取 Point 內的屬性 x 與 y 就跟存取自己的屬性一樣
// 3. 稱為 overriding
public String toString() { return "Center = " + "[" + x + ", " + y + "]" + ";
Radius = " + radius; }
}
19
Example
請你為一家公司設計一套人事資訊系統,
這套系統要能夠讓人事室的員工隨時新增、
刪除、修改、以及查詢員工資料。
首先,討論我們需要記錄員工的哪些資料
經仔細的討論後,我們發現員工分成兩類 -- 領
固定薪資的員工以及依照工作時數的員工(當
然還有可能是領取營業績效的員工)。
請以 specialization 以及 generalization 的方式
來完成繼承架構。
20
Inheritance
Inheritance is-a relationship
Aggregation has-a (or part of) relationship
An employee has a birthdate
class Employee {
String name;
Date birthdate;
}
The relationships between Shape, Point, Circle, and Rectangle.
Inheritance vs. Aggregation
to be discussed later.
conclusions: use them wisely.
21
Exercise
範例
Imagine a publishing company that markets both books
and CDs. This company asked you to write a program
to display their products properly on the Web. After
studying their requirements, you found out the
information required for books includes book title,
price, author name, and page numbers. The
information required for CDs are CD title, price,
singer's name, and playing time. Please design an
appropriate inheritance hierarchy for this program.
22
Upcast and Dynamic Binding
假設我們有一個繼承架構,其根節點為「人」,
而其子節點為「白種人」、 「黃種人」、和「黑
種人」。 由於每一個子類別的物件同時也是一個
父類別的物件(如每一個黃種人都是 人,但是每
一個人卻不一定是黃種人),所以 Java 允許子類
別的物件 upcast 到父類別的物件。
Connecting a method call to a method body is called binding.
When binding is performed before the program run, it's called
early binding or static binding. When the binding occurs at run-time,
we call it late binding, dynamic binding, or run-time binding.
23
Upcast and Dynamic Binding
Vector
Vector 的元素都是 Object,而 Object 是所有
Java 類別的父類別(或者稱之為祖先類別)
利用 Worker 以及 Vector 來產生 WorkerRecord.
24
Upcast and Dynamic Binding
import java.util.*;
public class WorkerRecord {
//private Vector<Worker> records =
//
new Vector<Worker>();
private Vector records = new Vector();
public WorkerRecord() {}
public WorkerRecord(Worker w) {
records.add(w);
}
public void setRecords(Worker w) {
records.add(w);
}
public Worker getRecords(int idx) {
if (idx < records.size())
return (Worker) records.elementAt(idx);
else
return null;
}
public double getSalary(int idx) {
if (idx < records.size())
return ((Worker) records.get(idx)).calcSalary();
else
return -1.0;
}
public static void main(String[] args) {
WorkerRecord r = new WorkerRecord(new
Worker(40));
r.setRecords(new Worker(65));
System.out.println(r.getSalary(0));
System.out.println(r.getSalary(1));
}
}
25
Example
import java.text.DecimalFormat;
import javax.swing.JOptionPane;
public class UpCasting {
public static void main( String args[] ) {
Point pointRef, p;
Circle circleRef, c;
String output;
p = new Point( 30, 50 );
c = new Circle( 2.7, 120, 89 );
output = "Point p: " + p.toString() + "\nCircle c: " + c.toString();
// upcasting: use the "is a" relationship to refer to a
// Circle with a Point reference
pointRef = c; // assign Circle to pointRef
// upcasting 之後要注意的是你能用的 methods 都只是
// base class 內定義過的,否則會 compilation error
//output += "\nCircle c (via pointRef): " + pointRef.area();
26
Example
// 非常有意思的是這個 toString() 呼叫的是 Circle 的
// toString() 而不是 Point 的 toString()。
output += "\n\nCircle c (via pointRef): " + pointRef.toString();
// 有意思的是經過 upcasting,雖然 pointRef 是 Point,
// 但是卻可以檢測出其實他代表一個 Circle 的物件
if (pointRef instanceof Circle)
output += "\npointRef is an instance of Circle";
else
output += "\npointRef is NOT an instance of Circle";
27
Example
// Use downcasting (casting a superclass reference to a
// subclass data type) to assign pointRef to circleRef
circleRef = (Circle) pointRef;
output += "\n\nCircle c (via circleRef): " + circleRef.toString();
DecimalFormat precision2 = new DecimalFormat( "0.00" );
output += "\nArea of c (via circleRef): " + precision2.format( circleRef.area() );
// Attempt to refer to Point object
// with Circle reference
// 下面這個敘述不可以,因為「不是所有的人都是黃種人」
// for details, please refer to "downcasting".
//circleRef = (Circle) p;
JOptionPane.showMessageDialog( null, output,
"Demonstrating the \"is a\" relationship",
JOptionPane.INFORMATION_MESSAGE );
System.exit( 0 );
}
}
28
Upcast and Dynamic Binding
從之前的範例,我們清楚的知道,如
果要善用 dynamic binding,子類別中的
方法最好也在父類別中定義,如此一
來,當我們呼叫一個物件行為的時候,
可以由系統自動的依照物件的真正型
態來 binding 到正確的方法
以 Circle 以及 Rectangle 為例
以人事系統為例
29
Upcast and Dynamic Binding
在把之前的人事系統為例,假設我們要求寫一個
程式,使得使用者可以輸入 10 個員工,而這十個
員工有些是 SalaryEmployee,有些是
HourlyEmployee,可以事先我們不知道他們各別是
多少個,使用者又不知道將來可能會輸入的順序
這個類似快打旋風中,程式無法事先知道使用者會選用哪一個角
色
解法(概念)
我們都知道 SalaryEmployee 和 HourlyEmployee 都是 Employee
(upcast 可以完成),所以…
而我們設計的時候,又可以善用 dynamic binding
重要結論:Employee 物件有時候是 Employee,有時候是
SalaryEmployee,有時候又是 HourlyEmployee,這就是多型的概念。
30
Polymorphism
一個物件(如 employees[i])可以擁有一種
以上的「面像」(forms),而且「面像」 之間
又有一定的關係(這個關係就是能夠使用
多型的物件其資料型態必須是所有可能 出
現的面像的父類別),這就是「多型」的
由來。
Polymorphism means you can use a variable of a
superclass type to hold a reference to an object whose class
is the superclass or any of its subclasses.
31
Exercise
範例
Continue from the previous example. Please finish
a POS (Point-Of-Sale) program that will print
out the list of sold items and calculate the total
amount of the sold items.
32
Inheritance
Single Inheritance vs. Multiple Inheritance
A Famous Problem Diamond Problem
侏儸紀公園的年代
33
Inheritance
abstract class Animal {
abstract void talk();
}
class Frog extends Animal {
void talk() { System.out.println("Ribit, ribit."); }
}
class Dinosaur extends Animal {
void talk() { System.out.println("Oh I'm a dinosaur and I'm OK..."); }
}
// 要特別注意的是 Java 並不支援多重繼承。所以這段程式只是
// 用來說明 diamond problem 的概念
class Frogosaur extends Frog, Dinosaur { }
---------------------------------------------------------------------------------------------------------現在如果某個程式做了下列的宣告,
Animal animal = new Frogosaur();
animal.talk();
那麼問題就來了,這隻 Frogosaur 究竟要發出哪一種聲音呢?
34