PPT7 - NHU IMBI Lab
Download
Report
Transcript PPT7 - NHU IMBI Lab
第七部分
1
C#程式設計 – 南華大學資管系
C# 程式設計
程式架構(programming structures)1/3
傳統程序式程式設計(Procedural programming)
C#程式設計
將程式劃分為「Data」和「程式碼」兩個獨立的部分 (資料
的宣告和函式的定義散佈在整個程式,只有透過文件才能
指出它們之間的關聯)。
「結構化」和「模組化」解決程式碼的統整問題,卻沒有
顧慮到與資料整合。
不易維護,可重用性低,易出錯 (成本高)。
OOP (Object-oriented programming)
Software-IC
a piece
of software
an object
Data Specification
+ combine tightly
related functions (operating on
these data )
Encapsulation
封裝
2
物件之間以一種名為「訊息傳送的方式溝通」(方法的呼叫)
程式架構 2/3
不可直
接接觸
an object
啟動
Methods
• public
• Interface
• visible
message
(含訊息參數)
C#程式設計
Data
• private
• Information
hiding
• invisible
message
.
.
.
encapsulation
若要做到Software-IC,需要下列特性:
Encapsulation (class, object, message)
Inheritance
Polymorphism (dynamic binding)
3
程式架構 3/3
C#程式設計
OOP的三大特性:
Encapsulation
Inheritance
Polymorphism
透過這些概念所寫的程式,不僅可以大大的提供軟體
的可重用性,更可以使我們除錯更容易,寫作更有
效率。
4
Objects, Classes, and Instances 1/5
電腦可以作為一種模擬世界的工具。人類的學習和認知
行為,有相當的部分是建立在「具體化」、「抽象化」
和「分類」等過程。
C#程式設計
(a) 傳統程式語言:
被模擬事物的資料和行為 (如:計算、訊息交換、互動等)無法
有效地結合在一起。
(b) OOP:
將實體的某些特性「抽取」(abstract)出來以後,再予以對應。
並將其資料和處理方法通通整合於物件之內。
物件(object):外界真實事物的抽象對應
資料:代表物件的一些性質。
行為:物件能夠(被)作用的動作。
5
Objects, Classes, and Instances 2/5
真實事務有什麼特性、狀態、行為
-抽象化(abstraction),以便表達。
-根據這些抽象化後的特性與行為,我們可以依需要
C#程式設計
的不同加以適當的分類,而得到不同的類別 (Class)。
如:人、貓、狗、…-動物類
花、草、樹木、…-植物類
作者Class的instances
分類前
分類後
作者Class
讀者Class
6
0bjects
讀者Class的instances
Objects, Classes, and Instances 3/5
每一個東西都是objects,
分類後的各類叫做Class
屬於其Class的objects稱之為該Class的instances
C#程式設計
Every object is an instance of a class
Classes and Instances
class:由一群具有某些相同資料結構與相同行為的物件
經分類後所形成的集合。
instance:由class所產生的具有某些資料結構與行為的
物件。
同一個class的instance都具有相同的資料格式與相同的
操作程序。但資料格式的實際內容(值)則未必相同。
7
Object-Oriented Programming 1/5
C#程式設計
在OOP理論中的軟體系統,是由一群同心協力
的物件(可能屬於不同class),合力組織、分層
負責來完成所有的工作。
Encapsulation(封裝)
軟體複雜度日增,為了增加可重用性與易維護性,
將資料與相關的操作方法封裝成物件。外界無法直
接存取內部私人的資料,只能透過物件提供的公開
的窗口存取內部維護的資料。物件之間的互動經由
message的傳遞,啟動某些操作程序來達成。
8
Object-Oriented Programming 2/5
同樣的資料格式與操作程序(方法),不必在每個需要的
地方都重寫一次,只要歸納(分類)成一個class,再依需
要重製出所需的instance即可。
C#程式設計
Inheritance (繼承)
是否可以把class再分類呢?
如: 人、豬、狗-動物類
生物類
花、草、樹木-植物類
這個分類再分類的性質,就是所謂的繼承性。我們可以
在不同的class之間,歸納分類出一些共同的特性,再形
成一個class。
幾個class共同的部分,就可以藉由繼承的功能,移轉到另一個
較高階的class去。
Class本身的定義可以精簡化。
Class形成階層組織(hierarchy)。
9
Object-Oriented Programming 3/5
OA1, OA2, …, OAm
OB1, OB2, …, OBn
abstraction
abstraction
Class B
D1, D2, D3, D4
M1, M2, M3
D1, D3, D5, D6
M1, M2, M4
Class C
Super class
Subclass
Class A’
D2, D4
M3
繼承
D1, D3
M1, M2
C#程式設計
Class A
Instances:
OA1, OA2, …, OAm,
OB1, OB2, …, OBn
繼承
Class B’
10
OA1, OA2, …, OAm
D5, D6
M4
OB1, OB2,…, OBn
Object-Oriented Programming 4/5
Employee
Programmer
Subclass
C#程式設計
Manager
Super class
”is-a” rule:every object of the subclass is an object of the
super class (the opposite is not true)
you can use a subclass object whenever the program expects
a super class object (polymorphism)
11
Object-Oriented Programming 5/5
Polymorphism (多型、同名異式、Dynamic Linking)
C#程式設計
message 是被送到物件介面,用來啟動物件的工具,而
method 則是message送達介面以後,被選取的操作程序
一旦物件產生之後,要使用這個物件只要單純的把訊息送
給它。只有在程式執行時,才會真正鎖定需要的物件,並
將message和appropriate method連接在一起 (並非在
compiling time 就將它們的關係固定下來。)
12
物件 (OBJECT)
所有objects的共同特徵就是state(狀態)和behavior(行為)。例
如:「車子」的狀態包括速度、傳動方式是兩輪或四輪傳
動、是否開燈等;「車」的行為則包括轉方向盤、踩剎車和
加速等等。
real-world object
software object
state
data
behaviors
Methods
objects 讓 programmer以較容易,且更合乎邏輯的方式來解
決真實世界的問題。
C#程式設計
物件(object)如同真實世界的物體一樣,物體的狀態
資料可看成屬性(property、data member),物件的行
為動作可視為方法(method、member function)。簡單
地說,物件為方法+屬性的整合。
13
類別的定義 (P.16-7) 1/8
[存取範圍修飾字] class 類別名稱 {
// 主要成員(member)有屬性,方法和事件
C#程式設計
// 方法或屬性的宣告 (預設存取為private)
// 通常屬性宣告為private變數 (encapsulation)
// 方法(method)一定包含在類別之內,無法獨
立存在
}
14
類別的定義 2/8
定義MyTime類別,包含Hour, Minute, Second三個
屬性
C#程式設計
class MyTime {
int Hour;
int Minute;
int Second;
}
方案右鍵 > 加入
> 類別
> 名稱:MyTime.cs
.
.
.
namespace Project
{
class MyTime {
…
}
}
15
類別的定義 3/8
建立物件:
使用new運算子,依照類別藍圖來建立物件(配置
MyTime now = new MyTime();
C#程式設計
記憶體),傳回指向此物件的參考。
此時物件變數now所參考的物件,稱為類別
MyTime的一個實例或實體 (instance)
所有產生的物件均各自獨立分配到一份記憶體,
彼此不互相干擾。(實體變數)
16
類別的定義 4/8
成員的存取:(在表單類別的button_Click事件程序中)
物件(變數)名稱.成員名稱
now.Hour = 10;
now.Second = 30;
C#程式設計
now.Minute = 30;
產生編譯錯誤
‘ Project.MyTime.data’ 的保護層級導致無法對其進行存取。
Why??
因為成員的預設存層級為private (只能在同一類別中被存取)
(修正)將類別資料成員的存取層級改為public。
可被任何類別存取
17
類別的定義 5/8
class MyTime {
public int Hour;
public int Second;
C#程式設計
public int Minute;
}
-即可通過編譯
- 將物件內容輸出, OK
- now.Hour = 30; 合理嗎?? 如何檢查??
18
類別的定義 6/8
物件的封裝性(Encapsulation)
將保護的資料成員加上private存取修飾,宣告其僅供物件
內部使用。(information hiding)
C#程式設計
保護物件的資料成員,不要讓物件範圍以外的人有任何
更改資料進而破壞資料完整性的可能。
透過公開(public)或保護(protected)的方法管道,允許物件
外部的人能間接存取private的資料成員。
將private之資料成員與public之成員方法封裝起來,即為
encapsulation。
19
類別的定義 7/8
具封裝性的MyTime類別
class MyTime {
private int Hour;
private int Second;
C#程式設計
private int Minute;
public string getTime( ) {
return Hour + ”:” + Minute + ”:” + Second;
}
public void setTime(int h, int m, int s) {
Hour = h; Minute = m; Second = s;
}
}
20
類別的定義 8/8
now.Hour = 30; // X, 不能通過編譯
必須通過開放的method來進行
在setTime(~)內進行資料的檢查
public void setTime(int h, int m, int s) {
C#程式設計
now.setTime(30, 30, 30);
// 假設超出範圍,則不處理
if (h < 0 || h > 23) return;
if (m < 0 || m > 59) return;
if (s < 0 || s > 59) return;
Hour = h; Minute = m; Second = s;
}
21
練習:定義自己的類別Date
私有成員:day, month, year
(可用的) 公開成員(原型prototype):
public void setDate(int d, int m, int y);
public string show( ); //回傳的格式 ”m-d-y”
C#程式設計
class Date {
private int day;
private int month;
private int year;
public void setDate(int d, int m, int y) {
day = d; month = m; year = y;
}
public string show( ) {
return month + “-” + day + “-” + year;
}
}
22
練習:類別Date的使用 (測試)
輸出鈕
int y = Convert.ToInt32(txtYear.Text);
int d = Convert.ToInt32(txtDay.Text);
C#程式設計
int m = Convert.ToInt32(txtMonth.Text);
Date date = new Date();
date.setDate(d, m, y);
lblOutput.Text = date.show();
23
方法的多載(Method Overloading) P.16-18
練習:在類別MyTime中新增另一個setTime方法
C#程式設計
在C#的類別中允許定義兩個以上同名方法,但其傳
遞的參數個數或資料型態不同即可,此即「多載」
(overloading)。
1. public void setTime (int h, int m) {
if(h < 0 || h > 23) return;
if(m < 0 || m > 59) return;
Hour = h; Minute = m; Second = 0;
}
2. MyTime obj2 = new MyTime( );
obj2.setTime (21, 40);
24
類別的建構子(Constructor) P.16-21
建構子是特殊的方法,在物件建立的同時,建構子會自動被
呼叫,此方法通常用於設定資料成員的初值。
預設建構子
C#程式設計
類別的建構子名稱必須和類別名稱相同。而且,建構子沒有
回傳值(也不加上void) 。通常是使用public修飾子進行宣告
建構子支援多載
public MyTime(int h, int m, int s) {…...}
public MyTime(int h, int m) {…..}
為了統一檢查資料,可以將其獨立為一個private method
private bool validTime(int h, int m, int s);
25
新版的class MyTime 1/2
class MyTime {
private int Hour;
private int Minute;
public MyTime(int h, int m, int s) { // constructor
if( ValidTime(h, m, s) ) {
Hour = h; Minute = m; Second = s;
}
}
public MyTime(int h, int m) { // constructor
if ( ValidTime(h, m, 0) ) {
Hour = h; Minute = m; Second = 0;
}
}
C#程式設計
private int Second;
26
新版的class MyTime 2/2
…
C#程式設計
private bool validTime(int h, int m, int s) {
if (h < 0 || h > 23) return false;
if (m < 0 || m > 59) return false;
if (s < 0 || s > 59) return false;
return true; // 合法資料
}
} // class MyTime
MyTime t1 = new MyTime(9, 30, 50);
MyTime t2 = new MyTime(21, 40);
27
This和This()的使用
this關鍵字:指目前作用中的物件。在類別內呼叫同
類別的實體成員可加上this,通常可省略,有必要區
分時,才加上this。
this.Hour = Hour;
C#程式設計
public void setTime(int Hour, int Minute, int Second) {
this.Minute = Minute;
this.Second = Second;
}
this(~):呼叫同類別的令一建構子
public MyTime(int h, int m) : this(h, m, 0) { }
28
解構子(Destructor)
在物件(的記憶體)被釋放前,會自動被呼叫的方法。一般
用來釋放物件中佔用的檔案、網路、資料庫等資源。
C#程式設計
一般而言,C#程式並不需要進行太多的記憶體管理,因為
C#會自動進行記憶體回收的動作,將不會再被使用的物件
記憶體回收。(未必立即進行回收)
解構子的名稱是在類別名稱前加上“~” 所構成。
~MyTime() { //不可加上public
MessageBox.Show(“*** destructor ***”);
} // 必須Using System.Windows.Forms;
29
物件陣列
多個同類型或相容物件所構成的陣列
C#程式設計
MyTime tArray = new MyTime[3];
tArray[0] = new MyTime( );
tArray[0].setTime(21, 40);
tArray[1] = new MyTime(9, 30, 50);
tArray[2] = new MyTime(10, 30, 30);
MyTime tArray
●
●
●
H
21
M
40
S
0
●
H
9
H
10
M
30
M
30
S
50
S
30
30
練習:利用for迴圈印出物件陣列的內容
練習:class Date
1. 在class Date內加上兩個constructors
public Date() { // 自己定義default constructor
}
C#程式設計
day = 1; month = 1; year = 200;
public Date(int d, int m, int y) {
day = d; month = m; year = y;
}
2. // 利用TextBox輸入d, m, y
Date date1 = new Date(d, m, y);
lblOutput.Text = date1.show();
31
UML (Unified Modeling Language)之類別圖P.16-6
類別名稱
(class name)
成員方法
(member function)
-day:int
-month:int
-year:int
+<<Constructur>> Date()
+<<Constructur>> Date(int, int, int )
+setDate(int, int, int)
+show():string
C#程式設計
成員資料
(Data member)
Date
+: public
-: private
#: protected
32
練習:定義類別Person (1/4)
類別名稱:Person
成員資料
name : string // unknown (預設值)
–
age : int
–
gender : char // ‘M’
–
date : Date
// 19
C#程式設計
–
// (1, 1, 2000)內含物件成員
// has-a relationship
33
練習:定義類別Person (2/4)
成員方法
+<<constructor>> Person()
+<<constructor>> Person(string, int, char)
+setName(string)
+setAge(int)
C#程式設計
+<<constructor>> Person(string, int, char, Date)
+setGender(char)
+setDate(Date)
+getName() : string
+getAge() : int
+getGender() : char
+getDate() : Date
+show() : string
//格式:
名字 = Tom
年齡 = 21
性別 = 男
生日 = 10-30-1990
34
練習:定義類別Person (3/4)
class Person {
private string name;
private int age;
private char gender;
private Date date;
public void setName(string n) {
name = n;
}
public string getName() {
return name;
}
public void setAge(int a) {
age = a;
}
C#程式設計
public Person() {
name = "unknown"; age = 19; gender = 'M';
}
public Person(string n, int a, char g) {
name = n; age = a; gender = g;
}
public Person(string n, int a, char g, Date d) {
name = n; age = a; gender = g; date = d;
}
35
練習:定義類別Person (4/4)
}
C#程式設計
public int getAge() {
return age;
}
public void setGender(char g) {
gender = g;
}
public char getGender() {
return gender;
}
public void setDate(Date d) {
date = d;
}
public Date getDate() {
return date;
}
public string show() {
string str = "名字 = " + name + "\r\n";
str += "年齡 = " + age + "\r\n";
str += "性別 = " + gender + "\r\n";
str += "生日 = " + date.show();
return str;
}
36
Encapsulation
C#程式設計
因為Encapsulation的特性,object可被視為獨立的「
黑盒子」,他可以執行特定功能,我們只要知道可以
傳給盒子什麼東西,以及可以得到什麼結果,而不必
知道其內部的implementation(實作)。也就是說,
資訊從黑盒子的輸入端傳入,而從輸出端產生結果,
我們不必知道也不用關心其內部運作的情形
可以串接或整合數個「黑盒子」,它們各自執行其特
定功能,因此建立一個大而複雜的系統。由於
Encapsulation的特性,我們可以在不影響系統工作的
前提下,自由地替換另一更理想(效率)的「黑盒子
」。
37
類別Person的使用
string name = txtName.Text;
int age = Convert.ToInt32(txtAge.Text);
char gender = '男';
C#程式設計
if(rdbMale.Checked) gender = '男';
if(rdbFemale.Checked) gender = '女';
int y = Convert.ToInt32(txtYear.Text);
int m = Convert.ToInt32(txtMonth.Text);
int d = Convert.ToInt32(txtDay.Text);
Date date = new Date(d, m, y);
Person p = new Person(name, age, gender, date);
lblOutput.Text = p.show();
38
類別的靜態成員 (P.16-25)
C#類別可以宣告靜態成員,這是一種屬於類別本身的成員
,不需要產生物件即可使用。因此,可以將一些不會因個
別物件而有所差異的成員宣告為靜態。
靜態資料成員的記憶體僅有一份,由該類別所產生的所有物件共享
C#程式設計
類別成員的宣告若未加上static,則稱為實體(instance)成員;若加
上static,則稱為靜態成員。
實體成員的存取
物件名稱.實體成員名稱
靜態成員的存取
類別名稱.靜態成員名稱(如:Convert.ToInt32(~))
物件名稱.靜態成員名稱? (C#: X)
類別名稱.實體成員名稱(X)
39
在類別Person中新增靜態成員
記錄並且取得共產生多少個Person物件
有底線者為static member
Person
ctr記錄物件實體的個數
--– ctr : int(初始值為ø)
private static int ctr = 0;
--+ counter() : int
C#程式設計
counter()回傳目前已產生的物件數(ctr)
個數的紀錄:在每個Constructor中加入ctr++;
public static int counter() { return ctr; }
在表單中隨時更新Person物件的個數
“共有” + Person.counter() + ”人”
40
namespace(名稱空間) (P2-23, P.7-31)
我們以using statement來描述在每個程式裡所使用到的
namespace。
C#程式設計
namespace又稱為命名空間,可以建立類別的群組,方便
對大量的類別以階層式的結構進行分門別類,將相關的類
別放在一起,以利管理。每一群組以一個名稱來代表,能
夠減少類別名稱相同所產生的衝突。
例如:using System;
告訴編譯器我們使用System namespace,如此,允許我們在程式
中寫Console.WriteLine(~),而不使用
System.Console.WriteLine(~)。
同一專案中的程式碼,以專案名稱作為預設的名稱空間
41
.NET Framework類別函式庫
是一個龐大且良好組織結構架構的函式庫。其類別架構是使用稱為
namespace的階層類別架構,每一個名稱空間能夠擁有多個類別。
C#程式設計
每一階層的namespace是使用「.」運算子連接
使用using 名稱空間;
匯入所需的名稱空間,可以方便使用其內的類別
using System.Window.Forms;
42