C#OOP CH04 深入類的方法
技術標籤:c#
C#OOP CH04 深入類的方法
本章目標:
- 理解並會編寫類的建構函式
- 會實現方法過載
- 理解類之間的通訊
1. 建構函式
建構函式是類中一種特殊的方法,也叫構造方法,或者構造器,或者構造體,函式名與類名相同,不返回任何值,也不能用void修飾,主要完成物件的初始化工作。
建構函式在每次例項化類時 通過new關鍵字呼叫
1.1 無參建構函式:
預設情況下,系統會分配給類分配一個無參建構函式,並且沒有方法體,用來對成員變數進行初始化操作。
可以自定義一個無參建構函式,在方法體內對類的屬性進行初始化操作。
無參建構函式的語法為:
訪問修飾符 類名() { //方法體 }
1.2 帶參建構函式:
語法為: 引數列表一般用來給類的屬性賦值.
訪問修飾符 類名(引數列表)
{
//方法體
}
注意:
-
當我們建立一個類時,系統將自動給類分配一個預設的無參建構函式
而一旦定義了建構函式 系統將不再自動分配建構函式。
結構與列舉沒有建構函式
1.3 解構函式
解構函式(destructor) 與建構函式相反,當物件脫離其作用域時(例如物件所在的函式已呼叫完畢),系統自動執行解構函式。解構函式往往用來做“清理善後” 的工作(例如在建立物件時用new開闢了一片記憶體空間,應在退出前在解構函式中用delete釋放)。
以C#語言為例,解構函式名也應與類名相同,只是在函式名前面加一個波浪符
~
,例如~
stud( ),以區別於建構函式。它不能帶任何引數,也沒有返回值(包括void型別)。只能有一個解構函式,不能過載。
語法:
~ 類名()
{
//方法體
}
2. 方法過載(overload)
同一個類中 方法名相同 引數列表(引數個數,引數型別)不同 稱為方法過載。
注意 方法過載與返回值型別無關
2.1 構造方法過載
舉例如下:
public SE() { } public SE(int id) { this.ID = id; } public SE(int id,String name) { this.ID = id; this.Name = name; } // 注意 多個過載的建構函式之間 可以使用 this關鍵字呼叫 // 語法為: public SE(int id,String name) : this(id) { this.Name = name; }
> 補充訪問修飾符:
C#中的訪問修飾符 以及許可權
public: 公共訪問,不受任何限制
private: 私有訪問,只限於本類成員訪問,子類和例項都訪問不到,類中成員沒寫修飾符,預設為private
protected: 受保護的,只能在本類或是子類中訪問,例項不能訪問
internal: 內部訪問,只限於在此專案中訪問,其他都訪問不到 如果類沒寫訪問修飾符,預設為internal
3. 擴充套件
3.1 軟體設計模式之單例模式:
單例模式,是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。
通過單例模式可以保證系統中,應用該模式的類一個類只有一個例項。即一個類只有一個物件例項(例如 Windows系統中的回收站)
所以單例模式的要點有三個:
一是 :某個類只能有一個例項;
二是:它必須自行建立這個例項;
三是:它必須自行向整個系統提供這個例項。
設計核心:將構造器私有化,對外提供公有的獲取該類例項的方法
3.2 懶漢模式:
所謂懶漢模式,正如其名,比較懶,在類載入的時候並不建立自身例項,採用延遲載入的方式,只有在執行時呼叫了相關的方法才會被動建立自身的例項。
程式碼演示如下:
/// <summary>
/// 單例模式之懶漢模式
/// </summary>
public sealed class Singleton
{
private static Singleton single;
private Singleton() {}
public static Singleton GetInstance()
{
if(null == single)
{
single = new Singleton();
}
return single;
}
}
使用Main方法測試併發情況下,懶漢模式的執行緒安全問題,程式碼如下:
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
new Thread(()=>
{
Console.WriteLine(Singleton.GetInstance().GetHashCode());
}).Start();
}
Console.ReadLine();
}
控制檯輸出如圖所示:
從輸出結果分析,很明顯 , 在多執行緒下無法正常工作,這也是致命的缺陷。
現在對上面的示例進行修改,因為最簡單的方法就是考慮同步,這裡採用synchronized實現。
/// <summary>
/// 單例模式之懶漢模式
/// </summary>
public sealed class Singleton
{
private static Singleton single;
private static readonly Object obj = new object();
private Singleton() {}
public static Singleton GetInstance()
{
if(null == single)
{
lock (obj)//解決執行緒併發時 系統建立多個例項的問題
{
if (null == single)
single = new Singleton();
}
}
return single;
}
}
以上寫法能夠在多執行緒併發環境中很好地工作,並且看起來它也具備了延遲載入的特性。但是很遺憾,這種處理方式效率不高,可以說95%以上的情況都不需要同步。
那麼對於執行緒安全問題,還有另一種解決方式,即餓漢模式。
3.3 餓漢模式:
餓漢模式在類載入的時候就已經完成了初始化操作,所以類載入較慢,但是獲取物件的速度很快。由於餓漢模式在類初始化時就完成了例項化,所以它是不存線上程安全問題的。修改以上的程式碼:
/// <summary>
/// 單例模式之餓漢模式
/// </summary>
public sealed class Singleton
{
//餓漢式
private static Singleton single = new Singleton();
private Singleton() { }
public static Singleton GetInstance()
{
return single;
}
}
上述程式碼中修改了GetInstance()方法,直接返回single,而此例項在類載入時就已經自行例項化了。這種方式基於classloader機制,有效避免了多執行緒的同步問題。
但是,由於導致類載入的原因比較多,而此時單例類ConfigManager在類載入時就例項化,顯然沒有達到延遲載入的效果。
現在可以對比一下兩種方式:
懶漢模式,在類載入時不建立例項,因此類載入速度快,但是執行時獲取物件的速度較慢,具備延遲載入的特性,但是又存線上程不安全的問題。
餓漢模式在類載入時就完成初始化,所以類載入較慢,但是獲取物件的速度很快。
懶漢模式是“時間換空間”,餓漢模式是“空間換時間”,因為一開始就建立了例項,所以每次使用時直接返回該例項就好了。
在實際開發場景中,例項化單例類很消耗資源,我們希望它可以延遲載入,顯然餓漢模式並不能實現。那麼我們應該怎麼處理呢?
要想讓餓漢模式同時具備延遲載入的特性,可以搭配靜態內部類進行改造實現。
改造程式碼如下:
/// <summary>
/// 單例模式之餓漢模式
/// </summary>
public sealed class Singleton
{
//餓漢式
private Singleton() { }
//使用靜態內部類 解決餓漢模式的延遲載入問題
private static class Single
{
internal static readonly Singleton sing = new Singleton();
}
public static Singleton GetInstance()
{
retunr Single.sing;
}
}
總結:
對於單例模式的使用,不管是懶漢模式,餓漢模式,或者靜態內部類的方式,根據具體的業務需求而定。反正要遵守一個原則:
在整個程式執行期間,有且僅有一個例項。
若違背這一點,那麼即使設計的天花亂墜,也不是單例模式的實現。