發布與訂閱模式Pub/Sub它主要的概念為 : 定義一對多的關係,當一件事情發布時會同時通知所有的訂閱者 在 Javascript 與 Jquery 非常容易看到該模式的使用。例如 Jquery裡的on,下面的程式就可以想成,$('.SomeThing')為訂閱者,訂閱了click,如果click事件發生了,發布者就會執行doSomething。 $('.SomeThing').on('click'fucntion doSomething(){ //doSomething }); 該模式的優點在於解耦合,發行者與訂閱者不需要知道對方的存在。 而使用的時機為當一個對象改變時,需要同時改變其它對象,但確不知道實際有多少個對象時,這種情況下,就可以考慮使用Pub/Sub模式。 Pub / Sub 簡單版範例 var EventHub = { topics: {}, subscribe: function(topic, handler) { if(!this.topics[topic]){ this.topics[topic] = []; } this.topics[topic].push(handler); }, publish: function(topic, data) { if(!this.topics[topic] || this.topics[topic].length < 1) return; this.topics[topic].forEach(function(listener) { listener(data || {}); }); } }; 然後就可以使用了,首先訂閱一個Task,並且當Task被觸發時,會自動執行task函數。 EventHub.subscribe('Task',function task(data){ console.log(data + 'by Task1'); }); EventHub.subscribe('Task',function task(data){ console.log(data + 'by Task2'); }); 然後在來觸發Task。
在Javascript單線程與Javascript之Event Driven這兩篇文章中,我們大概了解了單線程與非同步事件的工作原理,在這篇中我們將會說明運用SetTimeout來處理非同步事件。 setTimeout基本用法 SetTimeout為Javascript的原生函數,主要的用法為在一個指定的延遲時間後執行某個函數。 下列程式碼為setTimeout的基本使用,代表在1秒鐘後執行console.log(“Hello”)。 setTimeout(function(){ console.log("Hello") },1000); 這邊要注意一點,雖然上面程式碼是設定1秒,但是Javascript為單線程,因此如過將程式碼修改如下,讓單線程被While阻塞,setTimeout就不會在1秒後執行,而是等while執行完在執行。 var start = new Date; setTimeout(function(){ var end = new Date; console.log('Time elapsed:', end - start, 'ms'); }, 1000); while (new Date - start < 2000) {}; <!-- tas --> 輸出結果: Time elapsed: 2002 ms --- setTimeout ( 0 ) 的意思 SetTimeout為在一個指定的延遲時間後執行某個函數,所以如果帶入(0),則是否意味馬上執行的意思?來看下面程式碼。 setTimeout(function(){ console.log("Hello"); },0) console.log("Mark"); 執行結果為: Mark Hello 嚴來來說不是立即執行,而是立即排進Task Quenu等待執行,等Call Stack空時它會至Task Quenu尋找工作,因此執行結果才為Mark Hello。 如果不知道Task Quenu或Call Stack可至該篇看Event Driven的觀念。 Javascript Event Driven
在Javascript單線程該篇文章中有提到,大部份這種單線程但可以處理非同步的語言都有共同的特性那就是事件驅動(Event Driven),它一般是由通過事件循環(Event Loop)與事件隊列(Event Queue)來實現。 事件驅動 ( Event Driven ) 與事件隊列( Event Queue ) 先來說說事件驅動(Event Driven),這種類型的程式執行流程基本上是由使用者的動作例如點擊了頁面或按了ENTER之類的事件來決定,而不像一些如批次程式設計(batch programming)是由程式開發者來決定。 我們來看看下面這張Philip Roberts在JSConf EU 2014講述Javascript event-loop時所出現的這圖。 首先左上角為V8 Javascript runtime,其中裡面的Stack代表JS接下來要做的事情(嚴格來說要做的任務被分配到的記憶體空間)由上至下來執行。Philip Roberts在演講中也有提到因javascript單線程而所擁有的等式。 one thread == one call stack == on thing at time 其中Stack裡面的工作有些是非同步事件,例如ajax或settimeout等,stack會將工作丟給WebApis該區塊進行(嚴格來說是v8中某個東西會丟),等到執行完後成,會發送個callback給callbackQueue,等到Stack完全清空時,會至callback queue裡尋找看看有沒有callback要執行。 Javascript程式碼單線程運行流程範例 我們將以下列這段簡單的程式碼來看Javascript的執行流程。 console.log("hi") setTimeout(function cb(){ console.log("there"); },5000); console.log("Mark Lin"); 首先為第一張圖,在還沒執行程式程式碼時,所有的Stack與Task Quenu都是空的。 然後我們開始執行,首先載入這段JS,Stack會產生main()這個區塊,再執行到 console.log('hi')時,也會在Stack產生console.log('hi')的區塊,並在Console印出hi,最後console.log('hi')工作完成,會從Stack中釋放出。 執行到setTimeoout,Stack會產生setTimeout的區塊,並且會向api發送工作,然後繼續往下執行。 執行console.log("Mark Lin"),最後工作剛成後,Stack全部清空。 Stack全部空間釋放完後,同時也發現剛剛對api的請求已完成,並且已將CallBack cb放置Task Quenu,並且由於Stack已清空,它會自動去Task Quenu尋找Task,這時發現了Cb然後就執行consoel.log("there")。 參考資料 https://www.youtube.com/watch?v=8aGhZQkoFbQ https://vimeo.com/96425312 http://www.ruanyifeng.com/blog/2014/10/event-loop.html
首先看看下面的程式碼,會發現永遠跑不出So sad,因為Javascript為單線程,雖然設定1秒過後isEnd為false,然後應該就直接跑出So sad,但因為被while一直佔住線程,因此永遠不會執行setTimeout事件,與console.log(“So sad”) 。 setTimeout(function () { isEnd = false; }, 1000); while (isEnd); console.log("So sad"); Javascript的單線程是指一個瀏覽器行程(process)只有一個JS的執行線程(但不代表瀏覽器是單線程),同一個時段內只會有一段代碼在執行,代表一次只能完成一件事,如果有多件事,就代表你要排隊,一件一件的處理,如果有一件事卡死或要做很久,就代表下面的事永遠不會執行,優點是簡單,環境單純,但缺點是如果其中一個事件很耗時間,會拖慢整個程式執行。 Javascript將事件分為兩種同步(Synchronous)與非同步(Asynchronous)來解決單線程的缺點。 同步( Synchronous ) 就是一個完成換下一個,下一個完再換下下一個處理,程式執行順序與任務的排列順序是相同的,如下程式碼。 console.log(1); console.log(2); console.log(3); 輸出結果。 1 2 3 非同步( Asynchronous ) 非同步為每一個任務都有一個CallBack,代表每個任務執行完後會執行該CallBack而不是執行下一個任務,因此程式執行順序與任務的排列順序是不相同的,下列以ajax為範例。 console.log(1); $.ajax({ url:"tests/1" success:function(data){ console.log(2); } }) console.log(3); 輸出結果。 1 3 2 也就是說,假設該ajax很耗時,你可以不用等到ajax執行完,才跑console.log(3),而是先給它個callback等ajax執完後自動插入回線程中執行console.log(2)。 為什麼 Javascript 是單線程 ? Javascript最初做為瀏覽器腳本語言,主要用途在於和使用者戶動與操作DOM,也因此如果該語言為多線程語言就會發生不少混亂,例如Javascript有兩個線程,一個線程針對某個DOM節點新增某些內容,而另一線程為刪除該節點,那瀏覽器要以那個為主?所以為了避免這些亂,因此Javascript被設計為單線程語言。 HTML5提出了Web Worker的標準,web worker是運行在瀏覽器的後台,並且子線程完全由主線程控制,並且不得操作 DOM,所以該標準並沒有影響javascript為單線程的本質。 Javascript 為單線程,又怎著非同步的執行呢 ? 通常這種語言為單線程,但又可以處理非同步的語言都有個一種共同點,那就是事件驅動event driven)機制,一般是由通過事件循環(Event Loop)與事件隊列(Event Queue)來實現。 參考資料 http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html http://sporto.
什麼是泛型呢 什麼是泛型呢~? 這個東西有看過吧,你有時後會在程式碼裡看到List這種寫法, 這代表List串列中,你可以存放『T』型別,例如List就是裡面存放string,List就是裡面存放int。也被稱為型別參數。事實上我們可以將範例想成簡單點,那就是一個可以讓你自由決定型別的功能。 為什麼要有泛型呢 假設需要我們建立一個ArrayList,但確發現要取出值都需要轉型,這是因為當你將某個物件存入ArrayList集合時,它的型別就隱含轉換成object了。只要是命名空system.Collection的集合類別都是如何(stack之類的) 轉型是沒什麼問題,但在處理集合時,常常都會需要使用迴圈來取出或存入集合元素,假設迴歸數很大很大的話,那就會對程式的執行速度產生一定的影響了(不過不嚴重)。還有一點就是,缺泛編輯時期的安全檢查。 泛型的優點 可以用不同的型別去做相同動作的事情如我上述程式碼的這段。 可以減少Boxing與UnBoxing,使效能增加。 讓程式碼更有彈性、重複使用程式碼。 泛型類別和方法 這邊寫個泛型的小範例,來知道一下大概的寫法。下列程式碼建立Car類別,其中Class Car<T,T1>被稱為『泛型類別』,而T power 被稱為『泛型參數』。 輸出結果 類別參數的條件約束 既然泛型可以讓我們自由決定型別,但有時候太自由也不太好,那我們要著麼樣來約束呢?如下,其中『where』就是就是限制的關鍵字,而『T』就是受限制的型別參數,最後Class就是限制的內容。 下列程式碼為多參數限定。 其中限制的內容請參考下圖,來源為MSDN。 我們這邊在來寫個簡單的小程式。 建立個Car類別,並且有二個型別參數T與T1,並限制T型別參數必預是『參數型別』。 然後我們用兩種寫法來測試看看,第一種為T指定為 string型別,第二種為T指定為int型別。 其中,string型別會正確執行,這邊別忘了string為參考型別喔! 而第二種int則會出錯。 注: 如果不知道實值與參考是啥的可以參考一下小弟寫的這篇實值型別與參考型別的記憶體配置 未繫結的型別參數有幾項注意事項 無法使用!= 和 == 運算子,因為不能確定實體的型別引數是否會支援這些運算子。 這些參數可與System.Object相互轉換或明確轉換成任何介面型別。 你可以與NULL比較。如果將未繫結的型別參數與NULL比較,那麼當型別引數為實值型別時一定會傳FALSE。 參考資料 http://frankiestudy.blogspot.tw/2012/09/c.html http://msdn.microsoft.com/zh-tw/library/512aeb7t.aspx http://msdn.microsoft.com/zh-tw/library/d5x73970.aspx http://msdn.microsoft.com/zh-tw/library/kx37x362.aspx
什麼是委派 委派是以特定參數清單和傳回型別表示對方法的參考型別。 當您具現化委派時您可以使其執行個體具有相容簽章和傳回型別的所有方法。(MSDN) 白話文來說,委派方法是一種參考型別(Type),可以用來將方法當做引數傳遞給其他方法。 圖為委派型別的宣告範例 為什麼要用委派 從類別的設計者來看,在設計類別時,可能會碰到某個方法需要額外處理,但又不想把該處理想在這個類別裡,因為有可能變化很多,又或是無法預先得知處理的規則。 (註 : 這部份主要參考Huan-Lin的文章) 簡單用個情境來說明委派的用法 維京老大有一艘戰船,這艘船是老大專門買來給小弟用去打劫的(主要原因是因為老大怕死和麻煩),為了維護自身利益,老大定了一個用船契約範本,上面定了兩個規定分別為回傳string型別與輸入一個string型別的參數,小弟需要自行寫一份參考老大契約範本的契約,裡面一定要符合這兩項規定,小弟才能拿這份契約去和老大借船,然後執行自行寫的打劫計畫。 依上述的模擬情境來寫個程式碼來看看 ~首先先宣告一個委派方法,這就是維京老大所寫的契約範本,上面規定,小弟的契約裡需要符合兩個條件分別為回傳string型別與 輸入一個string型別的參數 public delegate string Attack(string str); 然後小弟1這時想要和老大借船來幹一票大的~~ ,所以開始寫契約,如下,有沒有符合老大的範本要求呢??『回傳string型別』與『輸入一個string型別的參數』,嗯都有,拿去給老大看應該會答應! public string Attack_Plan1(string str) { //這邊可以小弟可自訂自已的攻擊計畫 //反正最後有回傳黃金(string型別)給老大就好 Console.WriteLine(str); return "給老大的黃金" ; } 這時小弟1就跑去和老大借船. 老大:嗯很好有符合,~ 努力去(為我)打劫吧! private void button1_Click(object sender, EventArgs e) { //C# 2.0寫法 Attack attack_plan = Attack_Plan1; GoToAttackWithBattleShip(attack_plan, "Attack"); } private void GoToAttackWithBattleShip(Attack attack_plan, string str) { textBox1.Text = attack_plan(str); } 其中這時又來個小弟2,他也想要船,但他沒注意到契約範本規則,然後建立了下面的契約,不符合傳入一個string型別的參數
存取修飾詞 存取修飾詞 說明 public 無任何存取限制。 internal 只能在自已類別與專案(組件)中其它類別進行存取。(不包含其它專案)。 protected 只能在自已類別和子類別中存取。 protected internal 只能在目前專案(組件)與子類別存取。 private 在自已類別存取。 封裝的使用 封裝的使用時機 : 封裝表示讓一個類別對其他類別隱藏特定資訊,這樣有助於防止程式發生臭蟲。 當你回頭編程已經有好一陣子沒有沒看程式碼時,很容易就會忘記當初你要它做什麼,那正是封裝能夠大展身手的地方。 封裝的精神 只要在必要時才讓欄位與方法為public 將物件想成黑箱。你並不在意該方法到底是怎麼運作的。你只在意它接受你提供的輸入,並回傳正確的結果。 減少程式BUG,因為相依性減少了。 封裝性不良好類別 首先我們先建立個,幾乎沒有使用到封裝的類別BagFamer,這個類別主要是計算該農場需要多少袋飼料來養牛。 農場所需飼料(袋) = 牛隻數量 * 每隻牛需要的飼料 BagOfFeed = NumberOfCows * FeedMulitplier 三個欄位 FeedMulitplier : 存放一隻牛需要多少袋飼料。 NumberOfCows : 存放這個農場有幾隻牛。 BagOfFeed : 存放這個農場需要多少飼料。 Tip.共同遵循的約定與慣例。
區別何謂屬性與何謂欄位 先來說說欄位,欄位(Field)是一個任意型別(Type)的變數,直接在類別(Class)與結構(struct)中宣告。(註: 型別(Type)就是Int 、bool這些在變數前的東東) public class Car { //這個就是欄位(Field) private int PeopleNumber; } 而屬性呢?,屬性(Properties)是欄位和方法的綜合體,也是直接在類別(Class)與結構(struct)中宣告,它可以提供完整的控制,你可以控制它為只能讀或寫,有時會與private 欄位(Filed)一起使用,怎麼控制呢,這就需要介紹存取子(accessor)。 public class Car { //這個就是屬性 public int PeopleNumber { get; set;} } 存取子 ( accessor ) 屬性的存取子包含讀取 ( Get )和 寫入 ( Set )。 Get存取子 get存取子可以用於傳回欄位值或計算它並且回傳。 下列程式碼為Test 類別,有公開屬性PeopleNumber,設定為『只能讀』,但寫成降出錯喔,因為一定要有初始值。 class Test { public int PeopleNumber { get ;} } 要改成下列程式碼,才正確。 class Test { //設定唯時一定要給它值。不然會出錯。 public int PeopleNumber { get {return 10 ;} } } 試試看寫入值的話,則有人會打斷你的腿。
部份類別 ( Partial Class ) 部分類別使用時機大都在處理大型專案時,將類別分散至個別檔案,可讓多位程式設計師進行運作。 程式碼說明建立部分類別的方法,就是加上關鍵子『partial』。 //部分類別(Employee其中一個組件) public partial class Employee { public string PracticeTime; public void DoWork() { } } //部分類別(Employee其中一個組件) public partial class Employee { public string GoToDinner() { return "GoToDinner" ; } } protected void Page_Load(object sender, EventArgs e) { Employee Employ = new Employee { PracticeTime = "100" TextBox1.Text = Employ.GoToDinner(); TextBox6.Text = Employ.PracticeTime; } 執行結果 GoToDinner 100 部分類別的特性 所有組件都必需在相同的命名空間(Namespace) 如果有任何組件宣告為abstract則被視為抽象,如果宣告為Sealed則被視為密封,如果其中一繼承某基底類別,整個型別都會繼承 任何組件都可以指定不同的基底介面,最後的型別會實作所有部份宣告的任何介面 部份方法的特性 部分方法的簽章是在部分型別中的一部分定義,而其實作是在型別的另一部分中定義。
Interface概念 介面(Interface)你可以將他想成是商品契約,所有要商品的交易,都要經過這個商品契約來決定,例如裡面說交易單位是XXX,就是XXX,裡面如果說要在那交易,就是在那交易,不然有人(編譯器)會打斷你的腿的…很恐怖的… Interface使用時機 有時候,你必須根據物件能夠做什麼來將它們歸類。 想要做到類似C++中的多重繼承功能。 程式說明 建立UnitityCar的類別,該類別為未來車的概念。它可以飛(Fly)和跑(Run),但如果這時讓他繼承飛機類別讓他可以飛,有些飛機的屬性與方法不需用到,但如果在車類別新增飛的動作,但其它種車不會飛啊…。所以這時就需要用到Interface。 首先新增兩個Interface分別為ICanFly 與 IDrive。ICanFly定義飛的方法Fly() 與飛的速度FlySpeed。IRun定義跑的方法Run()與跑的速度RunSpeed (註:新增IRun Interface只是要給各位官爺看多個Interface使用) //宣告ICanFly介面 interface ICanFly { //介面不可以包含『欄位』。 string flySpeed { get ;} //介面不存放資料,因為不能增加欄位 //string test = "Hello"; //任何實作該介面的類別必需具備一個接受Fly()的方法。 string fly(); } //宣告IDrive介面 interface IDrive { //driveSpeed屬性,但介面不儲存資料,所以不會有欄位。 string driveSpeed { get ; set; } //任何實作此介面的類別,必需具備接受 drive() 方法。 string drive(); } UnitityCar 繼承基底類別 Car,並實作 IDrive 與 IcanFly ,記得任何實作介面的類別都必需符合它的方法與屬性。 //繼承基底類別Car //並實作IDrive與IcanFly Interface //假設UnitityCar在未來,他有兩個種類方法Drive與Fly。 public class UnitityCar :Car , IDrive, ICanFly { //由於在未來飛行速度(FlySpeed),有限制100, //因此設立唯讀的FlySpeed,不給人修改。 //一定要有!
使用修飾詞abstract,限定類別只能被繼承 在Class Car 前增加abstract,表是該類別只能繼承、不能實作,也被稱為抽象類別。 //父類別 //增加『abstract』修飾詞,讓該類別只能繼承。不能實作。 public abstract class Car { //車子的速度 protected string Speed; //車子的顏色 protected string Color; // 定義建構子,預設Speed為50,Color為Blue public Car() { Speed = "50"; Color = "Blue"; } //定義車子移動的方法。 public string DriveCar(string a) { return "正在開『" + Color + "』的車" + "時速『" + Speed + "』在移動" ; } } 抽像類別的特性 抽象類別不能實體化。 抽象類別可能包含抽象方法與存取子。 無法使用『Sealed』修飾詞,因為兩個意思完全相反。 衍生自抽象類別的非抽象類別必須包含所有繼承抽象方法和存取子的實作。 抽象方法的使用 抽象方法只能存在於抽象類別中。不然會出錯喔。 //父類別 //增加『abstract』修飾詞,讓該類別只能繼承。不能實作。 public abstract class Car { //車子的速度 protected string Speed; //車子的顏色 protected string Color; // 定義建構子,預設Speed為50,Color為Blue public Car() { Speed = "50"; Color = "Blue"; } //定義車子移動的方法。 //抽象方法宣告,沒有提供實際的實作,因此並沒有方法主題。 //抽象方法只能存在於抽象類別中。 public abstract string DriveCar(); } 子類別,使用Overried,來進行抽象類別覆寫。
特點 1 - 使用 Sealed 關鍵字使類別不能被繼承 下列為簡單的Sealed範例。 父類別Class Car ,有兩個屬性分別為Speed與Color,並自行訂定建構子Car() ,以及DriveCar()方法,在這範例中我們將Car類別,新增Sealed修飾詞,主要目的為不然其它類別繼承。 /// <summary> /// 父類別 /// </summary> public sealed class Car //增加Sealed { //車子的速度 public string Speed; //車子的顏色 public string Color; /// <summary> /// 定義建構子,預設Speed為50,Color為Blue /// </summary> public Car() { Speed = "50"; Color = "Blue"; } //定義車子移動的方法 public string DriveCar() { return "正在開『" + Color + "』的車" + "時速『" + Speed + "』在移動" ; } } 子類別BMWCar 繼承父類別Car,並有自行定義建構子BMWCar() ,以及BMWPower屬性。由於父類別Car有加Sealed因此無法被繼承。依下列程式碼,會找不到父類別的Speed與Color,而出現錯誤訊息。
Virtual 修飾詞 子類別的方法名稱和父類別的方法名稱一樣,著麼辦呢 ? virtual 關鍵字的用途是修改方法、屬性或事件宣告,以及允許在衍生類別中給予覆寫。通常使用的時機是在未來預期該方法可能會被子類別覆寫(override),則此方法必須宣告Virtual。 //父類別 public class Car { //車子的速度 public string Speed; //車子的顏色 public string Color; // 定義建構子,預設Speed為50,Color為Blue public Car() { Speed = "50"; Color = "Blue"; } //定義車子移動的方法。 //在該方法加上Virtual,讓子類別可以覆寫該方法。 public virtual string DriveCar() { return "正在開『" + Color + "』的車" + "時速『" + Speed + "』在移動" ; } } Override 修飾詞 Overrride修飾詞為需要用來修改或擴充父類別的方法、屬性,則需要給予該方法或屬性進行宣告。 // 子類別繼承Car public class BMWCar :Car { //BMWCar類別建構子 public BMWCar() { Speed = "BMW500"; Color = "BWM_Red"; } //BMW的屬性引擎 public string BMWPower; //定義車子移動的方法 //使用存取修飾詞Overried,來進行覆寫 public override string DriveCar() { return "正在開『" + Color + "』的車" + "時速『" + Speed + "』在移動" + "『Override』" ; } } 執行結果 正在開『BMW_Red』的車時速『BWM500』在移動『Override』 Override 修飾詞特性 注意 1 你不能覆寫非虛擬或靜態方法。被覆寫的父類別方法必須是Virtual、abstract、Override。
繼承為物件導向的三大特性之一(封裝、多型),你可以想像老爸與兒子的關係,兒子會繼承老爸所擁有的特徵(屬性)和)財產(方法)(現實上不一定,但請官爺們想簡單點),兒子可能會有老爸的大鼻子或小嘴巴,並且可以開著老爸的車(財產)出去玩,這就是繼承。 繼承父類別(基底類別 Base Class)的類別就被稱為子類別(衍生類別 Derived Class),子類別繼承了父類別的屬性與方法。 繼承的傳遞 : 你也會繼承到你阿公的東西 繼承是可以傳遞,Class C 繼承至 Class B,而 Class B 繼承至 Class A,則 Class C 會繼承至 Class A、B 白話文就是,你也會繼承到你阿公的東西。 以下為繼承程式碼 /// <summary> /// 父類別 /// </summary> public class Car { //車子的速度 public string Speed; //車子的顏色 public string Color; /// <summary> /// 定義建構子,預設Speed為50,Color為Blue /// </summary> public Car() { Speed = "50"; Color = "Blue"; } //定義車子移動的方法 public string DriveCar() { return "正在開『" + Color + "』的車" + "時速『" + Speed + "』在移動" ; } } /// <summary> /// 子類別繼承Car /// </summary> public class BMWCar :Car { //BMW的屬性引擎 public string BMWPower; } 以下紅色框框的部份就是從父類別Car繼承而來的屬性與方法
物件導向基本概念為『類別』與『物件』 基本上保哥這篇文章已經寫的很清楚了保哥 (保哥),但知識的學習還是要經過自已的腦袋與手加眼睛,所以小弟我也用自已的意思來表達這兩個東西的概念。 類別 小弟是把類別想成是『汽車藍圖』,它定義好了汽車的屬性與方法, 但它沒有實體(Instance),也就是說,你必須實作這張汽車藍圖它才能產生實體(可以開的車~)。 class Car { //定義車子的速度欄位 public int Speed; //車子的顏色欄位 public string Color; //定義車子移動的方法 public string DriveCar() { return "正在開『" + Color + "』的車" + "時速『" + Speed.ToString() + "』在移動"; } } 物件 就是實際做出來的車。以程式術語來說,運用汽車藍圖做出車的過程就是所謂的 『實體化』系統會自動給予物件記憶體。以下為實體化的C#程式碼。 //實體化Car類別為MyCar物件,並設定欄位Speed為100、Color為Red Car MyCar = new Car { Speed = 100, Color = "red" }; TextBox1.Text = MyCar.DriveCar(); 執行結果 正在開『red』的車時速『100』在移動 建構子或建構函式 ( constructor ) 其中Car MyCar = new Car ,即為產生一個名叫MyCar的Car實體。 new Car 除了產生實體,它還會幫你呼叫一個名為Car()的方法。該方法就是所謂的建構子(constructor)。