透過.NET C# 程式實作 OO 建國科技大學資管系饒瑞佶

Similar documents
物件導向與事件驅動

運算子多載 Operator Overloading

Microsoft Word - 投影片ch11

Microsoft PowerPoint - 13_ClassAndObj.ppt

主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new

CHAPTER VC#

投影片 1

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應

建立Android新專案

新・解きながら学ぶJava

The Embedded computing platform

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

《大话设计模式》第一章

Microsoft PowerPoint - P766Ch06.ppt

投影片 1

任務二 : 產生 20 個有炸彈的磚塊, 放在隨機的位置編輯 Block 類別的程式碼 import greenfoot.; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) Write a description of class

untitled

Python a p p l e b e a r c Fruit Animal a p p l e b e a r c 2-2

untitled

untitled

10-2 SCJP SCJD 10.1 昇陽認證 Java 系統開發工程師 的認證程序 Java IT SCJD

投影片 1

Microsoft PowerPoint - ch6 [相容模式]

(Microsoft Word - wes _\246p\246\363\250\317\245\316LED\277O\305\343\245\334\252\254\272A.doc)

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

投影片 1

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

Dynamic Layout in Android

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

Microsoft Word - 01.DOC

導讀 ASP.NET HTML ASP 第一篇 基礎篇第 1 章 認識 ASP.NET ASP.NET ASP.NET ASP.NET ASP.NET 第 2 章 認識 Visual Studio 20 開發環境 Visual Studio 20 Visual Studio 20 第二篇 C# 程式

Microsoft Word - ch04三校.doc

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

Microsoft Word - 物件導向編程精要.doc

Microsoft PowerPoint - EmbSys102_JavaOOP [相容模式]

Microsoft Word - 第3章.doc

Visual C# 2010 與 UML 開發實戰 C# 第 5 章物件導向基礎 C# C# 第 6 章資料與變數 C# 第 7 章判斷式與迴圈 C# 第 8 章陣列與集合 C# 第 9 章偵錯與例外狀況處理 Visual Studio 2010 C# try...catch ix

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

Chapter 9: Objects and Classes

CC213

<ADB6ADB1C25EA8FAA6DB2D4D56432E706466>

Strings

105Tr_CIS1

單步除錯 (1/10) 打開 Android Studio, 點選 Start a new Android Studio project 建立專案 Application name 輸入 BMI 點下 Next 2 P a g e

2 WF 1 T I P WF WF WF WF WF WF WF WF 2.1 WF WF WF WF WF WF

06 01 action JavaScript action jquery jquery AJAX CSS jquery CSS jquery HTML CSS jquery.css() getter setter.css('backgroundcolor') jquery CSS b

全国计算机技术与软件专业技术资格(水平)考试

PowerPoint Presentation

一、

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2

Microsoft Word - chap12.doc

untitled

The golden pins of the PCI card can be oxidized after months or years

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

Spyder Anaconda Spyder Python Spyder Python Spyder Spyder Spyder 開始 \ 所有程式 \ Anaconda3 (64-bit) \ Spyder Spyder IPython Python IPython Sp

0 0 = 1 0 = 0 1 = = 1 1 = 0 0 = 1

多媒體應用 13 新增專案並完成版面配置 <ExMusic01> <activity_main.xml> ImageView ID imgplay ImageView ID imgstop ImageView ID imgfront TextView ID txtsong TextView ID t

建模与图形思考

Android Service

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F

(Microsoft Word - wes _\246p\246\363\250\317\245\316watchdog\250\276\244\356\265{\246\241\267\355\276\367.doc)

Microsoft PowerPoint - VB14.ppt

Java

第二章 簡介類別

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

09_Constructor

Microsoft PowerPoint - plan08.ppt

EJB-Programming-4-cn.doc

软件工程文档编制

(procedure-oriented)?? 2

Microsoft Word - chap10.doc

ASP.NET MVC Visual Studio MVC MVC 範例 1-1 建立第一個 MVC 專案 Visual Studio MVC step 01 Visual Studio Web ASP.NET Web (.NET Framework) step 02 C:\M

第二章 簡介類別

ii Vue Bootstrap 4 ES 6 Vue Vue Bootstrap 4 ES 6 Vue 2 vue html vue html vue Vue HTML 5 CSS ES 6 HTML 5 CSS Visual Studio Code h

Microsoft PowerPoint - C_Structure.ppt

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

雲端 Cloud Computing 技術指南 運算 應用 平台與架構 10/04/15 11:55:46 INFO 10/04/15 11:55:53 INFO 10/04/15 11:55:56 INFO 10/04/15 11:56:05 INFO 10/04/15 11:56:07 INFO


<4D F736F F D20A2B0A1D0A2B0A1D0A2B0A240A6CBAA4FC554BC4DB7ABA240A7D6AA4FBD6DB2DF2E646F63>

Transcription:

透過.NET C# 程式實作 OO 建國科技大學資管系饒瑞佶

物件導向程式設計 OOP 只要可以依據前述類別與物件方式設計程式的語言都可以來實現 OO 包括 :JAVA C++ C#... 也就是 OO 是設計方式, 不專屬於哪個程式語言 這裡選用.NET C#

開始前 -C# 程式語法與觀念對應 觀念 語法關鍵字 類別 class 實做類別 / 建立物件 new 繼承 : 不可以繼承 final 公開 public 不公開 private 不可 instance 的抽象類別 abstract 不可實際定義的抽象類別 interface 覆寫 override 當然還有更多

Visual C# 語法大規範 OOP 程式語言 大小寫有別 需要 ; 結尾 區段都是用 {} 包圍 都是 class 組成, 透過 name space 管理 // 或 /* */ 或 /// 作為註解

來實際作個範例 Class Car 屬性 + 方法 繼承 inheritance Class SubCar 屬性 + 方法

定義 Class Car 透過 Visual Studio Windows Form 操作

設定類別名稱為 Car

新建立的 Car 類別 透過 namespace 引用其他類別 類別所在位置 類別範圍

大家如果看預設就有的 Form1 透過 namespace 引用其他類別 類別所在位置 類別範圍

定義 Class Car 屬性 : 方法 :

建構子 constructor 類別中的一個特殊方法 透過這個類別建立物件時, 自動會執行的方法 方法名稱定義成與 Class 名稱一樣就可以 // 屬性 String car_type; // 車輛種類 int car_cc; // 車輛 cc 數 // 方法 // 建構子 public Car() { car_type = "Luxgen"; car_cc = 1800; }

其他方法 (1) 1 需要傳入兩個參數 public void setcar(string newcar_type, int newcar_cc) { // 設定屬性 car_type = newcar_type; car_cc = newcar_cc; }

2 其他方法 (2) 回傳值型態 public String getcar_type() { return car_type; } 需要回傳值

3 其他方法 (3) 回傳值型態 public int getcar_cc() { return car_cc; } 需要回傳值

完整的 Class Car 2 個屬性 1 個建構子 3 個方法

使用預設的 Form1.cs 來使用 Class Car 類別物件名稱 =new 類別名 ( 參數 );

透過 button1_click 事件呼叫取回預設的車樣式與 cc 數 private void button1_click(object sender, EventArgs e) { Car mycar = new Car(); // 顯示車輛內容 label1.text = " 車輛樣式 =" + mycar.getcar_type(); label2.text = " 車輛 CC 數 =" + mycar.getcar_cc(); }

Result

設定屬性資料並顯示 private void button2_click(object sender, EventArgs e) { // 透過類別 Car 建立物件 mycar Car mycar = new Car(); // 設定車輛種類與 cc 數 mycar.setcar(textbox1.text, Convert.ToInt16(textBox2.Text)); }

Result 結果不是我設定的資料? 4 1 3 因為沒有使用同一個物件 2

修改 button1_click 與 button2_click 只建立 1 份物件 取消分別建立的物件

結果正確了! result

設定整個 class 為 static 其他共用方式? 設定 class 物件為 static, 透過另一個 class

接著定義 Class SubCar(1) 繼承於前面建立的類別 Car

接著定義 Class SubCar(2) 繼承於前面建立的類別 Car

接著定義 Class SubCar(3) 繼承於前面建立的類別 Car

看一下 Car 類別

繼承 Class Car 建立 Class SubCar

先不在 SubCar 加任何屬性與方法 (1) 直接修改原 Form1 介面 加入一個按鈕

先不在 SubCar 加任何屬性與方法 (2) 直接修改原 Form1.cs 程式碼 建立 mysubcar 物件 private void button3_click(object sender, EventArgs e) { SubCar mysubcar = new SubCar(); label1.text = " 車輛樣式 =" + mysubcar.getcar_type(); label2.text = " 車輛 CC 數 =" + mysubcar.getcar_cc(); }

result

加入方法到 Class SubCar SubCar 中才有的方法 // 依據車種類回傳對應網站 public string gotourl(string car_type) { // 設定回傳值 string URLstring = ""; switch (car_type) { case "Nissan": URLstring = "http://new.nissan.com.tw/nissan"; break; case "Toyota": URLstring = "https://www.toyota.com.tw/"; break; } return URLstring; }

再加入同樣名稱方法到 Class SubCar OverLoading 覆載參數型態不同 public string gotourl(int car_cc) { // 設定回傳值 string URLstring = ""; switch (car_cc) { case 1: URLstring = "http://new.nissan.com.tw/nissan"; break; case 2: URLstring = "https://www.toyota.com.tw/"; break; } return URLstring; }

加入方法到 Class SubCar 使用 Overriding 覆寫 Override 取代 Car 類別中原有的方法 setcar // 覆寫 override 類別 Car 內的同名方法 public void setcar(string newcar_type, int newcar_cc) { // 設定屬性 car_type = " 從 SubCar 設定的車種 =" + newcar_type; car_cc = newcar_cc; } 變數的保護層級不正確

修改類別 Car 內的變數 ( 屬性 ) 保護層級 加入 public 修飾詞

完整的 Class SubCar 3 個方法 (overloading & override)

使用 Class SubCar 內的 setcar 方法 新加入的程式碼 private void button3_click(object sender, EventArgs e) { SubCar mysubcar = new SubCar(); // 呼叫 mysubcar 內的 setcar 方法 mysubcar.setcar(textbox1.text, Convert.ToInt16(textBox2.Text)); label1.text = " 車輛樣式 =" + mysubcar.getcar_type(); label2.text = " 車輛 CC 數 =" + mysubcar.getcar_cc(); }

result 2 1

呼叫 gotourl 方法 webbrowser

呼叫 gotourl 方法 private void button3_click(object sender, EventArgs e) { SubCar mysubcar = new SubCar(); // 呼叫 mysubcar 內的 setcar 方法 mysubcar.setcar(textbox1.text, Convert.ToInt16(textBox2.Text)); label1.text = " 車輛樣式 =" + mysubcar.getcar_type(); label2.text = " 車輛 CC 數 =" + mysubcar.getcar_cc(); webbrowser1.url = new Uri(mysubcar.gotoURL(1)); }

result

namespace 如果變動 Class Car 的 namespace, 那會影響什麼?

Form1 程式的改變 加入明確的 namespace 與類別名稱

Class SubCar 的改變 加入明確的 namespace 與類別名稱

讓 Class 不能被繼承 加入 sealed 關鍵字, 讓 Car 類別不能被繼承

幾個特殊的類別

有時候只定義而不實作 (implement) 抽象概念, 例如動物 現實講動物時是沒有意義的, 我們會問是人 狗 獅子或老虎, 也就是動物並不是具體可操作的 ( 物件 )( 無法物件化 ), 所以動物只要規範大方向, 例如動物都會移動, 那只要屬於 ( 繼承 ) 動物的都被要求要具體定義 (override 實作 ) 怎麼移動 稱為抽象類別

抽象類別 可以透過 abstract 語法定義 裡面可以定義具體方法 或抽象方法 抽象類別不可以用 new 建立物件 可以透過 interface 語法定義 (WCF 中就使用 ) 裡面不能定義具體方法 可以被多重繼承 可以用在 partial class 開發上

新加入一個 abstract class Animal

設定 class Animal 為抽象類別 abstract 設定為抽象類別

設定 class Animal 的方法 具體方法 abstract class Animal { // 具體方法 public string getdata(){ return " 來自 Animal 類別的資料 "; } // 抽象方法 public abstract string run(int how); } 抽象方法

加入 Form2

從 Form1 跳到 Form2 private void button4_click(object sender, EventArgs e) { Form2 f2 = new Form2(); f2.show(); f2.owner = this; // 設定 f2 的擁有者是 form1 this.hide(); }

從 Form2 使用類別 Animal private void button1_click(object sender, EventArgs e) { Animal myanimal = new Animal(); } 要如何使用 Animal 類別?

先使用一個類別 UseAnimal 繼承 Animal

在 UseAnimal 類別中會被要求實作 abstract 方法 使用 override class UseAnimal : Animal { public override string run(int how) { return " 通用的 run 方法 "; throw new NotImplementedException(); } }

此時就可以透過 UseAnimal 類別建立物件再回到 Fomr2 private void button1_click(object sender, EventArgs e) { UseAnimal myanimal = new UseAnimal(); // 呼叫 Animal 類別內的 getdata 方法 label1.text = myanimal.getdata(); }

result

接著加入一個 interface-plant

interface 不能定義具體方法 interface Plant { // 抽象方法 string getdata(); } 抽象方法

繼承實作 interface

繼承實作 interface 繼承 interface 實作 getdata 方法需要有 public 修飾詞 class UsePlant : Plant { public string getdata() { return " 來自 Plant 的資料 "; throw new NotImplementedException(); } }

Fomr2 private void button2_click(object sender, EventArgs e) { UsePlant myplant = new UsePlant(); label2.text = myplant.getdata(); }

result

Abstract vs. Interface 都可以只定義, 不實作 abstract 屬於 is-a 的概念, 例如定義一個鳥的 abstract 類別, 裡面有個 abstract 方法 飛, 那繼承鳥這個類別, 應該是老鷹或麻雀, 都會有飛這個方法, 也就是老鷹或麻雀是一種 (is-a) 鳥 Interface 屬於 有這種動作或行為 概念, 例如定義一個 飛翔 的 Interface, 裡面定義 飛 的方法, 那這個 Interface 可以被繼承做出飛機 鳥 火箭等類別或物件, 因為他們都有飛的行為 (is-a-part-of)

使用既有 class 例如按鈕

建立 Button 物件 使用既有的 Button 類別 建立方式 : 類別物件名稱 =new 類別名 ( 參數 ); Button bt1 = new Button(this);

建立與顯示按鈕物件 // 建立按鈕動態介面設計的基礎 Button bt = new Button(); bt.text = "ccc"; // 按鈕的位置 ( 正中央 ) bt.location = new Point((this.ClientSize.Width bt.width) / 2, (this.clientsize.height bt.height) / 2); // 按鈕加入 windows form this.controls.add(bt);

result

加入對應的事件 委派機制 // 按鈕加入事件 bt.click += new EventHandler(this.Btn_Click); void Btn_Click(Object sender, EventArgs e) { MessageBox.Show("test"); }

產生 Button 物件陣列 多個按鈕 -Button Array 委派 + 匿名函數 (lambda)

Button Array 事件

private void button3_click(object sender, EventArgs e) { Button[] buttonarray = new Button[3]; for (int i = 0; i< buttonarray.length; i++) { int index = i; buttonarray[i] = new Button(); buttonarray[i].location = new Point((i+1)*70,100+(i+10)*5); buttonarray[i].name = "button" + (i+1); buttonarray[i].text = "button" + (i + 1); buttonarray[i].size = new Size(70, 23); buttonarray[i].click += (sender1, e1) => this.display(index + 1); this.controls.add(buttonarray[i]); } } public void Display(int i) { MessageBox.Show("Button No :" +i); }

區別每個物件 private void button3_click(object sender, EventArgs e) { Button[] buttonarray = new Button[3]; for (int i = 0; i< buttonarray.length; i++) { int index = i; buttonarray[i] = new Button(); buttonarray[i].location = new Point((i+1)*70,100+(i+10)*5); buttonarray[i].name = "button" + (i+1); buttonarray[i].text = "button" + (i + 1); buttonarray[i].size = new Size(70, 23); //buttonarray[i].click += (sender1, e1) => this.display(index + 1); buttonarray[i].click += new System.EventHandler(this.Display); this.controls.add(buttonarray[i]); } } public void Display(object sender, EventArgs e) { var obj = sender as Button; MessageBox.Show("Button No :" + obj.name); }

多型 Polymorphism

多型 教科書定義 : Polymorphism means that the sender of a stimulus does not need to know the receiving instance s class. The receiving instance can belogin to an arbitrary class. If an instance sends a stimulus to another instance, but does not have to be aware of which class the receiving instance belongs to, we say that we have polymorphism. 一個訊息 (message or event or stimulus) 的意義是由接收者 (The receiving instance) 所解釋, 而不是由訊息發出者 (sender) 來解釋 也就是當程式在執行時, 只要接受者換成不同的物件或是 instance, 系統的行為就會改變, 具有這樣的特性就稱之為 polymorphism

例如 例如在一個班級中, 老師請學生搬桌子, 不論是請學生甲或是學生乙來搬, 老師 (sender) 同樣都會說 : 把桌子搬走 (message) 但學生甲 (receiving instance) 跟學生乙 (receiving instance) 搬桌子的方法並不相同, 學生甲也許是整張桌子抬起來, 學生乙可能是將桌子拖著走 ( 意義是由接收者 (The receiving instance) 所解釋 )

多型其他定義 當子類別的物件宣告或轉型成父類別的型別時, 還可以正確執行該子類別的行為時就具備多型 物件導向的多型機制, 是指當兩個以上的類別繼承同一種父類別時, 我們可以用父類別型態容納子類別的物件, 真正進行函數呼叫時會呼叫到子類別的函數, 此種特性稱之為多型

多型 以往程式在撰寫時就決定了要呼叫的動作或函式 但是在 OO 中設計了多型機制, 允許程式到執行階段才決定實際要呼叫哪一個動作或函式 例如動物 class 定義一個 run() 方法, 而動物可以被繼承實作成馬 獅子 老虎等動物, 每個都有 run 方法 等系統開始執行後, 在執行時若為獅子 ( 訊息接收者 ) 那就動態呼叫獅子的 run(), 以此類推

Animal 父類別 public string run() { return "Animal Run"; }

繼承 Animal 建立 AnimalCat 子類別 class AnimalCat : Animal { public string run() { return "Cat run"; } }

繼承 Animal 建立 AnimalDog 子類別 class AnimalDog : Animal { public string run() { return "dog run"; } }

使用多型呼叫

不使用多型呼叫 建立 2 個物件 設計階段就決定 決定要執行哪個物件

private void button1_click(object sender, EventArgs e) { // 建立 mycat 物件 AnimalCat mycat = new AnimalCat(); // 建立 mydog 物件 AnimalDog mydog = new AnimalDog(); int whichone = 1; switch (whichone) { case 1: label1.text= mycat.run(); break; case 2: label1.text = mydog.run(); break; } }

使用多型呼叫 執行階段決定 //// 第一種寫法 //AnimalCat cat = new AnimalCat(); //AnimalDog dog = new AnimalDog(); //showrun(dog); //// 第二種寫法 //AnimalCat cat = new AnimalCat(); //AnimalDog dog = new AnimalDog(); //Animal[] allanimal = {cat,dog }; //showrun(allanimal[0]); // 第三種寫法 Animal[] allanimal = new Animal[2]; allanimal[0] = new AnimalCat(); allanimal[1] = new AnimalDog(); showrun(allanimal[0]); private void showrun(animal obj) { label1.text = obj.run(); }

發現結果並不正確 答案永遠都是 "Animal Run 傳入 showrun 的都是型別為 Animal 的 AnimalDog 與 AnimalCat 物件, 雖然三者都有 Run, 但此時是以 Animal 父類別的 Run 為主

修改 Animal AnimalCat 與 AnimalDog 透過覆寫來達成

改得更直覺點

code 未來如果有其他動物要加入我們只要完成該動物的類別後在需要的地方建立物件並呼叫 showrun 就可以不需要再加入一堆 if 的判斷敘述維護上較為便利

差異? 多型的寫法 一般的寫法 如果只有幾個物件, 邏輯簡單, 那確實沒有差異但當物件數量變多, 邏輯變複雜時, 那就可以看到多型的好處

意思是 如果用一般寫法當物件變多時, 之後如果要修改顯示的方式, 那麼就需要到每個物件所在處修改 label1.text 這裡的語法, 維護上是一個負擔 使用多型寫法如果有修改, 我們只需要修改 showrun 內這一個地方的程式就可以 另外如果有額外的邏輯要處理, 我們也只要在 showrun 內進行異動就可以

所以, 使用多型時 程式碼可以寫的比較簡潔, 例如用一個迴圈來處理陣列等等方式, 避免寫一大堆的 if 或 switch 等等判斷式 以後需要加新工作時, 就在物件陣列中增加一個新物件, 不用再去更改 if 或 switch 區段程式, 這樣的寫法比較有彈性 當工作類型愈來愈多時, 此方法的效益就會很明顯 C# 中的委派也有類似機制, 針對的對象是方法