〔C# Note〕面向對象篇

面向對象編程的三大特點:封裝,繼承,多態。

一、封裝
封裝就是把數據組合在一起,形成一個對象。將類封裝了以後,對外提供可訪問的屬性和方法,外部對象通過這些屬性和方法訪問此對象的信息。
類是支持對象封裝的工具,對象則是封裝的基本單元。

封裝的好處:
1、良好的封裝能夠減少耦合。
2、類內部的實現可以自由地更改。
3、類具有清晰的對外接口。

封裝性主要由訪問修飾符來控制。
在這裏有五個訪問修飾符,public,private,protected,internal,protected internal。

public是“公共”的意思,若被這個訪問修飾符所修飾,那麼它會被任何地方訪問到。

private是“私有”的意思,被這個訪問修飾符所修飾的只能在它所在的類中被訪問。

protected是“保護”的意思,被這個訪問修飾符修飾的只能在它所在的類及其子類中被訪問。

internal是“內部”的意思,被這個訪問修飾符修飾的只能在它所在的項目內部被訪問。其他項目無法訪問。

protected internal是“內部受保護”的意思,被這個訪問修飾符修飾的只能在項目內該元素所在類及其子類中被訪問。

私有等級:private>protected internal>protected>internal>public
訪問修飾符

枚舉類型(enum)的默認修飾符爲public,不可被其他訪問修飾符修飾。

類中的字段,屬性,方法等成員的默認修飾符爲private可被其他任意修飾符修飾。

類(class)的默認修飾符爲internal,可被其他任意修飾符修飾。

接口(interface)的默認修飾符爲public,不可被其他修飾符修飾。

{關於接口}

//private interface Interface1錯誤在命名空間中定義的元素無法顯式地聲明爲 private、protected 或 protected internal
//internal interface Interface1 Internal雖然可以修飾接口,但是不建議去用internal。因爲我們的接口是要對外通信的,使用public以便於其他項目能夠重複利用此接口的代碼
public interface Internal1
{
//接口可以是方法、屬性和事件,但是不能有任何成員變量,也不能在接口中實現接口成員。接口不能被實例化。接口的成員默認都是公共的,因此不允許成員加修飾符。
//void Interface() { }錯誤“面向對象篇.Internal1.Interface()”: 接口成員不能有定義
void Interface();
}

結構體(struct)的默認修飾符爲private可被public,internal,private修飾。

public class ClassFather
{
private struct Date { public int day; public int month; public int year;};//結構成員默認爲private,在聲明結構體的時候對結構體內部元素前加上訪問修飾符
//這是一個私有的字段,表明字段可以被private修飾
private int fieldPrivate;
//這是一個公有的屬性,表示屬性可以被public修飾
public int FieldPrivate
{
//這是屬性的get方法,即取值方法,將私有字段fieldPrivate的值取出來。
get
{
return fieldPrivate;
}
//這是屬性的set方法,即賦值方法,將屬性的值賦值給私有字段。
set
{
fieldPrivate = value;
}
}
//這是一個公有的字段,表示字段可以被public修飾
public int fieldPublic;
//這是一個公有自動屬性
public int FieldPublic { get; set; }
//這是一個內部字段
internal int fieldInternal;
//這是一個受保護字段
protected int fieldProtected;
//這是一個內部受保護字段
protected internal int fieldProtectedInternal;
//這是一個私有的自動屬性
private int FieldPrivate_ { get; set; }
private void methodPrivate()
{
Console.WriteLine("這是一個私有方法");
}
public void methodPublic()
{


Date d;//與類一樣,但可以不用new關鍵字
d.month = d.year = d.day = 0;
Console.WriteLine("這是一個公有方法");
}
protected void methodProtected()
{
Console.WriteLine("這是一個受保護方法");
}
internal void methodInternal()
{
Console.WriteLine("這是一個內部方法");
}
protected internal void methodProtectedInternal()
{
Console.WriteLine("這是一個內部受保護方法");
}
public ClassFather(int field1,int field2,int field3,int field4,int field5)//通過構造函數將值傳遞給字段
{
this.fieldPrivate = field1;
this.fieldPublic = field2;
this.fieldProtected = field3;
this.fieldInternal = field4;
this.fieldProtectedInternal = field5; //使用this 關鍵字可以調用此類中的成員變量
}


//其他的修飾符不做舉例說明,大家可以自己嘗試。
}
class Program
{
static void Main(string[] args)
{
//實例化ClassFather對象
ClassFather cf = new ClassFather();
//cf.fieldPrivate = 0;錯誤“面向對象篇.ClassFather.fieldPrivate”不可訪問,因爲它受保護級別限制 該字段只能在生命所在類中被訪問並賦值
cf.fieldPublic = 0;//這個字段是public修飾的,所以在任何地方都是可以訪問並賦值的。
cf.fieldInternal = 0;//這個字段是internal修飾的,所以是可以訪問並賦值的。
//cf.fieldProtected = 0;錯誤“面向對象篇.ClassFather.fieldProtected”不可訪問,因爲它受保護級別限制 該字段是被protected修飾的,所以只能在該類及其子類中被訪問並賦值的
//cf.fieldProtectedInternal=0;錯誤“面向對象篇.ClassFather.fieldProtectedInternal”不可訪問,因爲它受保護級別限制 該字段是被protected internal修飾的,所以只能在該類及其同一項目內的子類中被訪問並賦值的
/************* 方法與字段同理 ***************/
//cf.methodPrivate();錯誤“面向對象篇.ClassFather.methodPrivate”不可訪問,因爲它受保護級別限制
cf.methodPublic();//這個方法是被public修飾的,所以在任何地方都是可以訪問並調用的。
//cf.methodProtected();錯誤“面向對象篇.ClassFather.methodProtected”不可訪問,因爲它受保護級別限制
cf.methodInternal();//這個方法是被Internal修飾的,只要是在這個項目內就可以被訪問並調用
//cf.methodProtectedInternal();錯誤“面向對象篇.ClassFather.methodProtectedInternal”不可訪問,因爲它受保護級別限制
}
}

輸出結果爲:
這是一個公有方法
這是一個內部方法

合理利用訪問修飾符可以使項目中的數據得到有效的保護。使代碼儘可能模塊化,以便維護與調試。

二、繼承
繼承指的是一個類可以用繼承於一個類的方式得到那個類裏除了構造函數與析構函數之外的所有成員。被繼承的那一個類稱爲基類(或父類),繼承的那一個類稱爲派生類(或子類)。

繼承的本質是代碼重用。子類在繼承父類既有的屬性和方法的基礎上,又有自己的特性。

繼承常用與提煉出相同的特性,放於父類,起到減少代碼重複的作用。

如果子類繼承與父類。第一、子類擁有父類非private的屬性和功能;第二、子類具有自己的屬性和功能,即子類可以擴展父類沒有的屬性和功能;第三,子類還可以以自己的方式實現父類的功能(方法重寫)。

子類可以從父類中繼承的成員有方法、域、屬性、事件、索引指示器,但對於構造方法不能被繼承,只能被調用。對於調用父類的成員,可以使用base關鍵字。

如果不使用繼承,如果要修改功能,那麼就必須在所有的重複的方法中修改,代碼越多,出錯的可能就越大,而繼承的優點是,繼承使得所有子類公共的部分都放在了父類,使得代碼得到了共享,這就避免了重複,另外,繼承可使得修改或擴展繼承而來的實現都較爲容易。

繼承也是有缺點的,如父類變,子類不得不變。繼承是一種類與類之間強耦合關係。

class ClassSon:ClassFather //繼承ClassFather類
{
public ClassSon(int field1, int field2, int field3, int field4, int field5)
: base(field1, field2, field3, field4, field5)
{
//使用base 關鍵字爲父類的成員變量賦值
}
}

三、多態
多態是指同一個消息或操作作用於不同的對象可以有不同的解釋,產生不同的執行結果。
在面向對象編程中多態性有兩種:靜態多態和動態多態。

多態表示不同的對象可以執行相同的動作,但要通過他們自己的實現代碼來執行。
1、子類以父類的身份出現。
2、子類在工作時以自己的方式(代碼)來實現。
3、子類以父類的身份出現時,子類特有的屬性和方法不可以使用。
當在同一個類中直接調用一個對象的方法時,根據傳遞的參數個數、參數類型和返回值類型等信息決定實現何種操作,就是靜態多態。
當在一個有着繼承關係的類層次結構中間接調用一個對象的方法時,調用經過基類的操作,就是動態多態。

靜態多態的實現——重載
重載是指允許多個同名函數,而這些函數的參數不同,或許參數個數不同,或許參數類型不同,或許兩者都不同。

class Program
{
static void overload()//靜態方法函數名前用static標誌
{
Console.WriteLine("這是一個重載方法,返回值爲空,參數爲空");
}
static int overload(int value)//以int 爲例,其他類型與int相同
{
Console.WriteLine("這是一個重載方法,返回值爲int,參數爲int "+ value );
return value;
}
static int overload(int value1.int value2)
{
Console.WriteLine("這是一個重載方法,返回值爲int,參數爲int,int " + value1 + value2 );
return value1;
}
static void Main(string[] args)
{
overload();
int value1 = overload(2);
int value2 = overload(3,4); //靜態多態 函數重載調用
}
}

輸出結果:
這是一個重載方法,返回值爲空,參數爲空
這是一個重載方法,返回值爲int,參數爲int 2
這是一個重載方法,返回值爲int,參數爲int,int 34

動態多態的兩種實現方法:抽象類和虛方法
抽象類:使用abstract關鍵字來定義抽象類。在抽象類中使用abstract關鍵字聲明一個抽象方法(但不定義)。在抽象類子類當中,必須使用override關鍵字重寫這個抽象方法,在方法中定義自己需要的功能。抽象類不能實例化。如果類中包含抽象方法,那麼類就必須定義爲抽象類。

虛方法:在父類當中使用virtual關鍵字來定義一個虛擬方法(可以定義功能)。在子類當中去過需要改變父類虛擬方法功能,可以使用override關鍵字去重寫父類的方法。除了字段不能爲虛擬的之外,其他的屬性、事件、索引器都可以使虛擬的

abstract class polymorphismFather //一個類中出現抽象方法,就必須把類聲明爲抽象類
{
public virtual void PolymorphismVirtual()
{
Console.WriteLine("這是一個父類虛方法");
}
public abstract void PolymorphismAbstsact();//抽象方法只聲明不定義
}

class polymorphismA:polymorphismFather //繼承抽象類polymorphisFather
{
public override void polymorphismVirtual()
{
Console.WriteLine("這是第一個子類重寫虛方法");
}
public override void polymorphismAbstract()
{
Console.WriteLine("這是第一個子類重寫抽象方法");
}
}

class polymorphismB:polymorphismFather
{
public override void polymorphismVirtual()
{
Console.WriteLine("這是第二個子類重寫虛方法");
}
public override void polymorphismAbstract()
{
Console.WriteLine("這是第二個子類重寫抽象方法");
}
}

class Program
{
static void Main(string[] args)
{
polymorphismFather pfA = new polymorphismA(); //將父類用里氏轉換法轉成子類對象
//調用方法時,先檢查子類又沒有對應的方法,沒有再向父類檢查,如此類推。
pfA.polymorphismVirtual();//調用子類polymorphismA 的重寫虛方法
pfA.polymorphismAbstract(); //調用子類polymorphismA 的重寫抽象方法

polymorphismFather pfB = new polymorphismB();
pfB.polymorphismVirtual();
pfB.polymorphismAbstract();
}
}

輸出結果爲:
這是第一個子類重寫虛方法
這是第一個子類重寫抽象方法
這是第二個子類重寫虛方法
這是第二個子類重寫抽象方法

面向對象思想:世間萬物皆對象

參考資料:
博客園–《面向對象基礎》-逆心
http://www.cnblogs.com/kissdodog/archive/2013/03/24/2979650.html

《C#程序設計》-楊律青 上海交通大學出版社

我是大一新生,最近在學習C#程序設計。這是根據自己的感悟總結的,如果有不足的地方歡迎大家在下方指出來幫我改正。自己第一次寫博客,希望能得到大家的鼓勵。

自己的第一幅插畫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章