前言
Day 9跟Day 10兩天分別說明了類別跟函式。
開始要講到重要的抽象概念(還是初學者的我遇到的,面試筆試的考題有蠻多都是從這裏的概念出來的)
對當時剛開始接觸到這個概念的我來說,有夠抽象,似懂非懂,當要求我詳細的描述,又似乎無法很好的解釋與說明。
首先提到物件,在網路上可以找到像下面這樣的相關定義。
在計算機科學中,物件是一個記憶體位址,其中擁有值,這個位址可能有標識符指向此處。物件可以是一個變數,一個資料結構,或是一個函式。是物件導向中的術語,既表示客觀世界問題空間中的某個具體的事物,又表示軟體系統解空間中的基本元素。
(恩...如果是身為初學者的我,看完上面的定義絕對是…滿頭問號啊!!!!!!)
就從類別跟物件的差異開始解釋起吧:
物件導向程式設計的主要目標是提高程式碼的可維護性、可擴展性和可重用性。它通常將複雜的系統分解為多個小型、可管理的物件,並且強調模組化和抽象化的設計方式。
這種方法有助於更好地理解和維護程式碼,並促進團隊協作。因此,物件導向概念在軟體開發中廣泛應用並被視為一種強大的編程範式。
那物件導向呢基本上就是把程式內的東西都變成以物件的方式呈現。
在這個程式中,物件與物件之間互相區別,但又藉由程式碼互相呼應。
簡單來說,類別是一個設計圖,它定義了物件應該長什麼樣子以及可以做什麼事情。
當我們需要一個具體的實例來處理特定任務時,我們創建一個物件,並基於該類別的定義來設定其屬性和執行相關的操作。
類別和物件之間的關係可以比喻為建造圖紙(類別)和實際建築物(物件)之間的關係。
圖紙告訴您如何建造房子,但實際的房子是根據這些圖紙所建造的。
同樣地,類別告訴電腦如何建立物件,而物件是根據這些類別的定義所建立的實例,用於執行特定的任務。
請問「類別」可不可以包含「物件」?
在物件導向程式設計中,一個類別(Class)是用來定義物件(Object)的模板或藍圖,沒有實體概念。
換句話說
類別描述了一個物件的結構、屬性和方法。物件則是根據這個類別的定義實際創建的實例。
所以,類別本身並不包含物件,它只是定義了物件應該具備的特性和行為。
當您創建一個物件時,您實際上是根據該類別的定義創建了一個物件的實例。這個實例是該類別的一個具體示例,包含了該類別定義的資料和方法。
總結來說,類別定義了物件的結構,但不包含物件本身。物件是根據類別的定義創建的實例。您可以根據同一個類別的定義創建多個不同的物件實例。
在物件導向程式設計中,繼承是一個重要的概念,它允許我們建立一個新的類別(子類別)基於現有類別(父類別)的屬性和方法。以下是一些關於繼承的重要觀念:
object
**的預設父類別。可以再舉一些其他的例子來說明繼承的概念:
1. 動物與具體動物
考慮一個簡單的動物層次結構。有一個基本的 Animal
類別,然後裡面有一些具體的動物類別,例如 Dog
和 Cat
。 Dog
和 Cat
是 Animal
的子類別。
public class Animal
{
public string Species { get; set; }
public void MakeSound() { }
}
public class Dog : Animal
{
public string Breed { get; set; }
}
public class Cat : Animal
{
public bool IsLazy { get; set; }
}
在這個例子中,Dog
和 Cat
繼承了 Animal
的屬性和方法。
例如,它們都有 Species
屬性,而且都可以執行 MakeSound
方法。
同時,Dog
有自己的 Breed
屬性,而 Cat
有 IsLazy
屬性。
2. 形狀與具體形狀
考慮一個簡單的圖形層次結構。有一個基本的 Shape
類別,然後有一些具體的形狀類別,例如 Circle
和 Rectangle
。
public class Shape
{
public double Area { get; set; }
public void Draw() { }
}
public class Circle : Shape
{
public double Radius { get; set; }
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
}
在這個例子中,Circle
和 Rectangle
繼承了 Shape
的屬性和方法。
例如,它們都有 Area
屬性,而且都可以執行 Draw
方法。
同時,Circle
有自己的 Radius
屬性,而 Rectangle
有 Width
和 Height
屬性。
多用合成,少用繼承
在設計軟體時,通常建議多用合成(Composition)而少用繼承。
合成是一種將現有類別的物件組合到新類別中的方式,而不是繼承其屬性和方法。這種方法更靈活,減少了類別之間的耦合性,並提高了程式碼的可維護性。
封裝是一種程式設計原則,它指的是將一個物件的狀態(屬性)和行為(方法)捆綁在一起,並將其隱藏在物件內部,只向外部提供有限的訪問接口。
封裝允許我們將物件的實現細節隱藏起來,只公開對外界有意義的操作。
封裝就像是你的銀行帳戶。
你有一個銀行帳戶,希望保護它的安全,不希望任何人都能夠輕易地進行資金操作。所以,銀行為你的帳戶提供了一個安全的密碼和存取卡。這個密碼和存取卡就像是你的帳戶封裝,只有你知道密碼並持有存取卡的人才能夠進行帳戶操作。
其他人,包括你的家人或朋友,不能直接訪問或管理你的銀行帳戶。他們必須經過授權的方式,例如提供密碼或存取卡,才能夠進行相關的交易。這就是一個封裝的概念,它將你的財務信息保護在安全的封裝內,只有授權的人才能夠訪問和操作。
在程式設計中,封裝也是類似的概念。你可以將數據和方法封裝在一個類別中,只有該類別的方法才能夠訪問它們。這樣可以確保數據的安全性和方法的可控性,同時隱藏了實現細節,使程式碼更加模組化和易於維護。
封裝的優點包括:
public
、private
、protected
**)來控制哪些部分的物件可以被外部訪問,這有助於實現良好的封裝。以下是一個簡單的 C# 類別示例,演示了封裝的概念:
public class Person
{
private string name; // 私有欄位,只能在類內部訪問
public Person(string name)
{
this.name = name;
}
// 公開的方法用於訪問 name 屬性
public string GetName()
{
return name;
}
// 公開的方法用於修改 name 屬性
public void SetName(string newName)
{
name = newName;
}
}
在上面的例子可以看到, name
的欄位設置為private的,只能在 Person
類別的內部訪問。然後,再寫兩個公開的方法 GetName
和 SetName
,用於查找和修改 name
屬性。這樣,外部使用者只能通過這些方法來與 name
互動,而不需要知道 name
的具體實現細節。
多型是一種物件導向程式設計的特性,它允許不同的類別共享相同的介面或基類,但具有不同的實現。多型的核心概念是:相同的方法名稱可以在不同的類別中有不同的實現,並且可以在運行時選擇適當的實現。
多型的優點包括:
在 C# 中,多型通常通過繼承和介面實現。以下是一個簡單的示例,演示了多型的概念:
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Some generic animal sound");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark! Bark!");
}
}
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Meow!");
}
}
在上面的程式碼中,Animal
類別中的 MakeSound
方法被標記為 virtual
。
這表示它是一個可以被子類別覆寫(override)的方法,當一個方法被標記為 virtual
時,它可以在子類別中重新實作(override),以提供不同的行為。
接下來的 Dog
類別和 Cat
類別都繼承自 Animal
類別,並使用 override
關鍵字來覆寫 MakeSound
方法。這意味著它們提供了自己獨特的 MakeSound
實作,不同於 Animal
類別中的預設實作。
當你建立 Dog
或 Cat
的實例並呼叫 MakeSound
時,它們會執行各自的覆寫實作,而不是 Animal
中的預設實作。這就是多型(polymorphism)的一個示例,其中不同的物件實例可以對相同的方法呼叫產生不同的行為。
像我們在Day 9 提到的多載(Overloading)就是多型的其中一種實現方式喔
第11天挑戰完成!!!