2. 繼承
2.4 繼承和訪問修飾符
2.5 黎克特制替換原則
3. 多型
封裝、繼承、多型是物件導向的三大特點,而在c#也是不例外,這篇文章將闡述封裝、繼承、多型的用法和思想。
封裝,就是將類的屬性和方法封閉起來,外部成員不可直接呼叫,只能通過預留的介面訪問。
封裝允許類自身的屬性和方法被一些可信物件操作,如繼承自該類的物件,而一些不可信的類則不允許其修改。在一定程度上保證了類內資料的穩定性。
同時,封裝也能夠簡化程式設計——有時候我們並不想知道其原理,只需要會呼叫即可。外部的物件只需要訪問乙個簡單的介面函式,就可以完成一件任務,很輕鬆的一件事。
訪問修飾符 class 類名類的訪問修飾符可以定義為private、protected、public,通過訪問修飾符,類的屬性或方法可以選擇是否允許被外部訪問,從而限制了外部的許可權,保護了內部的資料的穩定性。
訪問修飾符 class 類名屬性是物件的性質與物件之間關係的統稱。和字段一樣,屬性是類的成員,有訪問修飾符,有型別。set }…
類的成員;
}
通常,定義欄位為私有,然後再定義乙個與該字段對應的屬性,具有對外的set和get方法。如下圖:
public
class
guyget
}}
guy是乙個類,name是其欄位,而name是與其對應的屬性,name能夠被外部訪問,就好像對應name為public一樣,直接訪問。
get和set是屬性訪問器,get和set訪問器有預定義的語法格式,可以把屬性訪問器理解為方法。
set訪問器用於設定資料,value是呼叫屬性是賦給屬性的值;get訪問器用於返回資料,必須有return語句,其返回值與屬性類別是一致的。
在set和get方法裡,可以做相應的判斷和操作,可以將set和get看做乙個方法,在裡面做需要的操作。
當然,屬性也可以簡化:
public
class
guy}
繼承就是在已存在的類基礎上,建立乙個新類,保留原有類的屬性和方法,同時又可以增加新的內容。
已存在的類稱為基類或父類,新建的類稱為派生類或父類。
//基類
public
class
animal
public
animal
(string name)
//建構函式
}//派生類
public
class
dog:
animal
}
上面的**實現了dog類繼承自animal類,子類自動繼承了基類的屬性name。
呼叫base(引數列表)實現呼叫基類的帶引數的建構函式。即使不使用base(),編譯器也會先呼叫基類的不帶參建構函式,再執行子類的建構函式。
和c++不同,在c#中乙個子類只能有乙個父類,而c++是可以繼承多個父類的。繼承的單一性也使得c#的基礎關係比較簡單,易於管理維護。
object類是所有類的基類。clr執行時,要求所有的型別,不管是系統定義的類還是使用者自定義的類,都必須從object派生。
//1.隱式派生
class
guy//2.顯式派生
class
guy:
system.object
//兩者實際上是一樣。
當乙個子類被乙個新類繼承時,新的類不僅繼承子類的屬性和方法,子類的父類的內容也將繼承下來。
c#繼承的單根性與傳遞性的繼承關係,形成了樹狀層次結構,基類和它的派生類存在一種層次關係。
之前,關於類的定義時有講到訪問修飾符。在c#中,有4中不同的訪問修飾符:
(1)pirvate:只能在本類中被訪問,只可以被本類所訪問,不能被繼承。
(2)public:可以在專案外被訪問,任意訪問,可以被繼承。
(3)protected:只能在本類中被訪問,可以被繼承。
(4)internal:只能在同一程式集中被訪問,可以跨類。可以被繼承。
在c#中,新增了internal這一關鍵字。internal的作用域為同一程式集。程式集的概念可以理解為乙個工程、專案,編譯後的dll檔案或exe檔案。也就是說,internal修飾符修飾後,該類只能在單一工程內訪問,如果其他專案訪問是不行的。
這位博主關於internal的總結不錯
如果沒有顯式地定義訪問修飾符,則c#的預設訪問許可權如下。
(1)在namespace中的類、介面預設為internal。如果不是巢狀的類,命名空間或編譯單元內的類只可以顯式地定義為public、internal型別,不允許是其他訪問型別。
(2)在類中,所有的成員均預設為private。可以顯式地定義為public、private、protected、internal或protected internal訪問型別。
任何基類可以出現的地方,派生類一定可以出現。也就是說,可以用派生類物件代替基類物件,可以讓乙個基類的引用指向乙個派生類的物件。
//基類
public
class
animal
public
animal
(string name)
//建構函式
}//派生類
public
class
dog:
animal
}//栗子
dog dog =
newdog()
;//例項化物件
animal animal =
newdog()
;//使用黎克特制替換原則,基類物件指向派生類
在物件導向程式設計中,多型(polymorphism)是類的三大特性之一,從一定角度來看,封裝和繼承幾乎都是為多型而準備的。
封裝、繼承、多型這三大特性是相互關聯的,封裝是基礎,繼承是關鍵,多型性是補充。
多型性存在於繼承性之中,它是繼承性的進一步擴充套件。沒有繼承就沒有多型。通過多型可以實現**重用,減少**量,提高**的可擴充套件性和可維護性。
多型性分為編譯時的多型性和執行時的多型性
編譯時的多型性是通過過載來實現的。對於非虛的成員來說,系統在編譯時,根據傳遞的引數、返回的型別等資訊決定實現何種操作。具有執行速度快的特點。
//基類
public
class
animal
}//派生類
public
class
dog:
animal
}
過載是通過new修飾符來實現的,這樣dog類呼叫hello()時將覆蓋掉animal類的hello函式,呼叫自身的hello()函式。
執行時的多型性是指直到系統執行時,才根據實際情況決定實現何種操作。c#中執行時的多型性是通過重寫實現。具有高度靈活和抽象的特點。
//基類
public
class
animal
}//派生類
public
class
dog:
animal
}
重寫,需要將父類的hello()加上修飾符virtual,而子類的hello()加上修飾符override,表示重寫基類的虛方法。
如果使用黎克特制替換原則,即使用基類物件指向子類物件,那麼會出現問題:究竟是呼叫哪個函式呢?
(1)使用new過載,那麼還是呼叫基類的方法。
(2)使用virtual和overide重寫,那麼將呼叫子類自己的方法。
也就是說,基於重寫可以實現多型,而過載方法不行。
C 學習筆記(5) 封裝 繼承 多型
封裝 每個物件都能包含它能進行操作所需要的所有資訊,這個特性稱為封裝,因此物件不必依賴其他物件來完成自己的操作。封裝的好處 l 良好的封裝能夠減少耦合。l 類內部的實現可以自由地修改。l 類具有清晰的對外介面。繼承 物件的繼承代表了一種 is a 的關係,如果兩個物件a和b,可以描述為 b是a 則表...
203 07 05 封裝 繼承 多型
繼承 1 oc是單一繼承 2 封裝 隱藏內部 m檔案 實現 穩定外部 h檔案 介面。屬性封裝了例項變數 方法封裝了具體實現 類封裝了方法和屬性 封裝的好處 使用更加簡單,變數更加安全,可以隱藏內部實現細節,開發速度快 3 私有變數 private,私有方法 在.m中實現,在.h中沒有宣告,私有成員變...
python 20200317封裝 繼承 多型
展開python 中的 self 相當於c 中的this指標。init self init方法 構建方法,當你在初始化乙個物件時 這個方法就會在物件被建立時 自動呼叫 class ball def init self,name attention self.name name def kick se...