1. 程式人生 > >C#父類引用指向子類物件

C#父類引用指向子類物件

父類引用指向子類物件指的是:

例如父類Animal,子類Cat,Dog。其中Animal可以是類也可以是介面,Cat和Dog是繼承或實現Animal的子類。

Animal animal = new Cat();

即宣告的是父類,實際指向的是子類的一個物件。

那這麼使用的優點是什麼,為什麼要這麼用?可以用這幾個關鍵詞來概括:多型、動態連結,向上轉型

也有人說這是面向介面程式設計,可以降低程式的耦合性,即呼叫者不必關心呼叫的是哪個物件,只需要針對介面程式設計就可以了,被呼叫者對於呼叫者是完全透明的。讓你更關注父類能做什麼,而不去關心子類是具體怎麼做的,你可以隨時替換一個子類,也就是隨時替換一個具體實現,而不用修改其他.

以後結合設計模式(如工廠模式,代理模式)和反射機制可能有更深理解。

下面介紹Java的多型性和其中的動態連結,向上轉型:

面向物件的三個特徵:封裝、繼承和多型;

封裝隱藏了類的內部實現機制,可以在不影響使用者的前提下修改類的內部結構,同時保護了資料;

繼承是為了重用父類程式碼,子類繼承父類就擁有了父類的成員。

方法的重寫、過載與動態連線構成多型性。Java之所以引入多型的概念,原因之一是它在類的繼承問題上和C++不同,後者允許多繼承,這確實給其帶來的非常強大的功能,但是複雜的繼承關係也給C++開發者帶來了更大的麻煩,為了規避風險,Java只允許單繼承,派生類與基類間有IS-A的關係(即“貓”is a “動物”)。這樣做雖然保證了繼承關係的簡單明瞭,但是勢必在功能上有很大的限制,所以,Java引入了多型性的概念以彌補這點的不足,此外,抽象類和介面也是解決單繼承規定限制的重要手段。同時,多型也是面向物件程式設計的精髓所在。

理解多型,首先要知道“向上轉型”。

我定義了一個子類Cat,它繼承了Animal類,那麼後者就是前者是父類。我可以通過 

Cat c = new Cat(); 
例項化一個Cat的物件,這個不難理解。但當我這樣定義時: 

Animal a = new Cat(); 
這代表什麼意思呢? 

很簡單,它表示我定義了一個Animal型別的引用,指向新建的Cat型別的物件。由於Cat是繼承自它的父類Animal,所以Animal型別的引用是可以指向Cat型別的物件的。這就是“向上轉型”。

那麼這樣做有什麼意義呢?因為子類是對父類的一個改進和擴充,所以一般子類在功能上較父類更強大,屬性較父類更獨特, 定義一個父類型別的引用指向一個子類的物件既可以使用子類強大的功能,又可以抽取父類的共性。 所以,父類型別的引用可以呼叫父類中定義的所有屬性和方法,而對於子類中定義而父類中沒有的方法,父類引用是無法呼叫的; 

那什麼是動態連結呢?當父類中的一個方法只有在父類中定義而在子類中沒有重寫的情況下,才可以被父類型別的引用呼叫; 對於父類中定義的方法,如果子類中重寫了該方法,那麼父類型別的引用將會呼叫子類中的這個方法,這就是動態連線。