所有的面向對象語言都具有3個基本特征,C#也是不例外的。
1、封裝
封裝指的是把類內部的數據隱藏起來,不讓對象實例直接對其操作。在C#中,封裝可以通過public private protected和internal等關鍵字來體現。
C#對保護內部數據狀態提供了一種方式,叫做屬性機制。
public class Person
{
private string _name;
private int _age;
public string Name
{
get{return _name;}
set{_name=value;}
}
public int Age
{
get{return _age;}
set
{
//在屬性定義中,可以根據系統的業務邏輯添加邏輯代碼
if(value<0 || value>120)
{
throw(new ArgumentOutOfRangeException("AgeIntProperty",value,"年齡必須在0-120之間"));
}
_age=value;
}
}
}
2、繼承
在C#中,一個類可以繼承另外一個已有的類,子類會獲得基類除構造函數和析構函數以外的所有成員。同時靜態類和密封類是不能被繼承的。
C#與C++不一樣,只支持單繼承。
//基類
public class Animal
{
private int _age;
public int Age
{
get{return _age;}
set
{
if(value<0 || value>10)
{
throw(new ArgumentOutOfRangeException("AgeIntProperty",value,"年齡必須在0-10之間"));
}
_age=value;
}
}
}
//子類(馬)
public class Horse:Animal
{}
//子類(羊)
public class Sheep:Animal
{}
有一點需要注意:子類並不能對父類的私有成員進行直接訪問,它只可對保護成員和公有成員進行訪問。
私有成員也會被子類繼承,但子類不能直接訪問私有成員,子類可以通過調用公有或保護方法來間接地對私有成員進行訪問。
2.1 密封類
public sealed class SealedClass
{
//在這裡定義類成員
}
//密封類不能作為其他類的基類,下面代碼編譯時會出錯
public class Test :SealedClass
{}
2.2 子類的初始化順序
當我們初始化一個子類時,除了會調用子類的構造函數外,同時也會調用基類的構造函數。子類的初始化順序如下:
(1)初始化類的實例字段;
(2)調用基類的構造函數,如果沒有指明基類,則調用System.Object的構造函數;
(3)調用子類的構造函數。
下面就通過一個實例來說明:
//父類
public class Parent
{
//②調用基類的構造函數
public Parent()
{
Console.WriteLine("基類的構造函數被調用了");
}
}
//子類
public class ChildA:Parent
{
//創建一個ChildA對象時
//①初始化它的實例字段
private int FieldA=3;
//③調用子類構造函數
public ChildA()
{
Console.WriteLine("子類的構造函數被調用");
}
public void Print()
{
Console.WriteLine(FieldA);
}
}
class Program
{
static void Main(string[] args)
{
ChildA childa=new ChildA();
}
}
3、多態
多態的定義:即相同類型的對象調用相同的方法卻表現出不同行為的現象。
3.1 使用virtual和override關鍵字實現方法重寫
只有基類成員聲明為virtual或abstract時,才能被派生類重寫;而如果子類想改變虛方法的實現行為,則必須使用override關鍵字。
public class Animal
{
private int _age;
public int Age
{
get{return _age;}
set
{
if(value<0 || value>10)
{
throw(new ArgumentOutOfRangeException("AgeIntProperty",value,"年齡必須在0-10之間"));
}
}
}
//幾乎所有動物都具有發出聲音的能力
//但是對於動物來說,每種動物發出的聲音是不一樣的
public virtual void Voice()
{
Console.WriteLine("動物開始發出聲音");
}
}
//馬(子類),子類應重寫基類的方法,以實現自己特有的行為
public class Horse:Animal
{
//通過override關鍵字來重寫父類方法
public override void Voice()
{
Console.WriteLine("馬叫");
}
}
//羊(子類)
public class Sheep:Animal
{
//通過override關鍵字來重寫父類方法
public override void Voice()
{
Console.WriteLine("羊叫");
}
}
class Program
{
static void Main(string[] args)
{
Animal horse=new Horse();//把子類對象賦給父類變量
horse.Voice();
Animal horse=new Horse();//把子類對象賦給父類變量
horse.Voice();
Console.ReadKey();
}
}
如果在子類中還要訪問父類中虛的方法,就必須要用base關鍵字來完成調用。base.Voice();
對於上面那種情況,建議把Animal類設置成抽象類,采用abstract關鍵字來防止在代碼中直接創建這樣類的實例。
3.2 阻止派生類重寫虛成員
public class Horse:Animal
{
//采用sealed關鍵字,Horse就不能再擴展Voice方法了
public sealed override void Voice()
{
//調用基類方法
base.Voice();
Console.WriteLine("馬叫");
}
}
3.3 使用新成員隱藏基類成員
可以在子類中采用new的關鍵字來隱藏父類成員
public class Horse:Animal
{
public new void Voice()
{
......
}
}
采用這樣的形式,如果要調用父類的方法,只能把對象強制轉換成父類類型。
4、所有類的父類
在C#中,所有的類都派生自System.Object類,底下是Object類的一些成員:
public class Object
{
//方法
//構造函數
public Object();
//虛成員,子類可以重寫這些方法
public virtual bool Equals(object obj);
protected virtual void Finalize();
public virtual int GetHashCode();
public virtual string ToString();
//實例成員
public Type GetType();
public object MemberwiseClone();
//靜態成員
public static bool Equals(object objA,object objB);
public static bool ReferenceEquals(object objA,object objB);
}
小結:此篇文章講的是C#在面向對象方面的一些基本知識點,如果能把這3個特性搞熟透的話,在做項目的時候,你的思路就會比較多了。