摘要:繼承和多態(tài)*繼承可以讓class具有一種特殊的能力,即實現(xiàn)class本身定義的所有功能外,還可以對父類(或稱為基類、超類)的某些屬性和功能進行擴展,這樣的類我們稱之為子類(或派生類)。繼承有如下的幾個規(guī)則:1. 可傳遞性:如: C是B的子類,B是A的子類,那么C會同時繼承B和A;(object為所有類的基類)2. 唯擴展性:子類應是對父類的擴展,而不能在子類除去父類里面的定義;3. 構(gòu)造函數(shù)和析構(gòu)
繼承和多態(tài)
*繼承可以讓class具有一種特殊的能力,即實現(xiàn)class本身定義的所有功能外,還可以對父類(或稱為基類、超類)的某些屬性和功能進行擴展,這樣的類我們稱之為子類(或派生類)。
繼承有如下的幾個規(guī)則:
1. 可傳遞性:
如: C是B的子類,B是A的子類,那么C會同時繼承B和A;(object為所有類的基類)
2. 唯擴展性:
子類應是對父類的擴展,而不能在子類除去父類里面的定義;
3. 構(gòu)造函數(shù)和析構(gòu)函數(shù)不能被繼承:
除去構(gòu)造函數(shù)和析構(gòu)函數(shù)不能被繼承,其他的成員都能被繼承(注意區(qū)別:能被繼承和能被訪問,是兩個概念)
4. 重載屏蔽性:
如果子類定義了和父類成員同名的新成員,那么會執(zhí)行重載和覆蓋邏輯。但要明白的是,這樣做,并不是刪除了父類的這些成員,而是不能再訪問這些被重載和覆蓋的成員而已。
5. 子類可以從父類的虛方法、虛屬性以及虛索引器進行重載(即多態(tài))
我們可以借用override關(guān)鍵字對父類的虛方法、虛屬性以及虛索引器進行重載;
同時,我們也可以借用override關(guān)鍵字對抽象父類的抽象方法進行重載。
abstract和virtural的區(qū)別:
(1) abstract可以修飾class以及abstract class內(nèi)部的函數(shù)、屬性和索引器;而virtual不可以修飾class;
?。?) abstract修飾內(nèi)部的函數(shù)、屬性和索引器的時候,必須在abstract class才可以;而且abstract函數(shù)、屬性和索引器不可以在abstract class里面有實現(xiàn),但virtual必須要有實現(xiàn)。
?。?) virtual既可以修飾abstract class里面的函數(shù)、屬性和索引器,也可以修飾一般class里面的函數(shù)、屬性和索引器;
*基礎知識擴展:什么是索引器?
索引器允許類或者結(jié)構(gòu)的實例按照與數(shù)組相同的方式進行索引取值,索引器與屬性類似,不同的是索引器的訪問是帶參的。
A. 索引器和數(shù)組比較:
(1)索引器的索引值(Index)類型不受限制;
(2)索引器允許重載;
(3)索引器不是一個變量;
B. 索引器和屬性的不同點
(1)屬性以名稱來標識,索引器以函數(shù)形式標識;
(2)索引器可以被重載,屬性不可以;
(3)索引器不能聲明為static,屬性可以;
下面一個簡單的例子可見一斑:
public class MyClass { private string[] _strArray; public MyClass(int length) { this._strArray = new string[length]; } public string this[int index] { get { if (index < this._strArray.Length) { return this._strArray[index]; } return null; } set { if (index < this._strArray.Length) { this._strArray[index] = value; } } } }
static void Main(string[] args) { MyClass myClass = new MyClass(3); myClass[0] = "A"; myClass[1] = "B"; myClass[2] = "C"; Console.WriteLine(myClass[0]); Console.WriteLine(myClass[1]); Console.WriteLine(myClass[2]); Console.ReadLine(); }
運行結(jié)果:
A
B
C
6. 子類只能繼承一個父類(class),而可以繼承多個接口(interface)(多重繼承)
*多態(tài)性:同一操作作用于不同的類的實例,將產(chǎn)生不同的執(zhí)行結(jié)果,即不同類的對象收到相同的消息時,得到不同的結(jié)果。
下圖所示的類之間繼承關(guān)系和多態(tài)用法,可以讓大家更好了解這些概念的意義:
具體的實現(xiàn)代碼:
public abstract class Creature { private string _spiece; public Creature(string spiece) { this._spiece = spiece; } public string Spiece { get { return this._spiece; } } public abstract void Breath(); }
public class Animal : Creature { private bool? _sex; public Animal(string spiece) : base(spiece) { this._sex = null; } public bool? Sex { get { return _sex; } } public virtual void Run() { Console.WriteLine("I am running..."); } public override void Breath() { Console.WriteLine("I am breathing by animal respiration..."); } }
public class Monkey : Animal { public Monkey(string spiece) : base(spiece) { } public void ClimbTree() { Console.WriteLine("I am climbing tree..."); } public override void Run() { Console.WriteLine("I am running with two legs, sometimes with four legs..."); } public override void Breath() { Console.WriteLine("I am breathing with lung..."); } }
public class Fish : Animal { public Fish(string spiece) : base(spiece) { } public override void Run() { Console.WriteLine("I am running in the water with fins..."); } public override void Breath() { Console.WriteLine("I am breathing with cheek..."); } }
public class Plant : Creature { public Plant(string spiece) : base(spiece) { } public override void Breath() { Console.WriteLine("I am breathing by plant respiration..."); } }
public class Tree : Plant { public Tree(string spiece) : base(spiece) { } //重載Breath()內(nèi)部調(diào)用base.Breath(),其實和不寫沒啥區(qū)別,這里只是想告訴大家本質(zhì)是什么。 public override void Breath() { base.Breath(); } }
程序運行測試代碼:
class Program { static void Main(string[] args) { Creature creature001 = new Animal("Animal"); Console.WriteLine(creature001.Spiece); creature001.Breath(); Console.WriteLine("—————————————————————————"); Creature creature002 = new Plant("Plant"); Console.WriteLine(creature002.Spiece); creature002.Breath(); Console.WriteLine("—————————————————————————"); Animal animal001 = new Animal("Animal", true); Console.WriteLine(animal001.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal001.Spiece, GetSexName(animal001.Sex))); animal001.Breath(); animal001.Run(); Console.WriteLine("—————————————————————————"); Creature monkey001 = new Monkey("Monkey", true); Console.WriteLine(monkey001.Spiece); monkey001.Breath(); Console.WriteLine("—————————————————————————"); Animal animal002 = new Monkey("Monkey", false); Console.WriteLine(animal002.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal002.Spiece, GetSexName(animal002.Sex))); animal002.Breath(); animal002.Run(); Console.WriteLine("—————————————————————————"); Creature fish001 = new Fish("Fish", true); Console.WriteLine(fish001.Spiece); monkey001.Breath(); Console.WriteLine("—————————————————————————"); Animal fish002 = new Fish("Fish", true); Console.WriteLine(fish001.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", fish002.Spiece, GetSexName(fish002.Sex))); fish002.Breath(); fish002.Run(); Console.WriteLine("—————————————————————————"); Animal animal004 = new Monkey("Monkey", false); Console.WriteLine(animal004.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal004.Spiece, GetSexName(animal004.Sex))); animal002.Breath(); animal002.Run(); Console.WriteLine("—————————————————————————"); Monkey jack = new Monkey("Monkey", true); Console.WriteLine(jack.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", jack.Spiece, GetSexName(jack.Sex))); jack.Breath(); jack.Run(); jack.ClimbTree(); Console.ReadLine(); } private static string GetSexName(bool? value) { string sexName = null; if (value == null) { sexName = "undefined"; } else { sexName = value.Value ? "male" : "female"; } return sexName; } }
運行結(jié)果:
Animal I am breathing by animal respiration... ————————————————————————— Plant I am breathing by plant respiration... ————————————————————————— Animal Spiece:Animal; Sex:male I am breathing by animal respiration... I am running... ————————————————————————— Monkey I am breathing with lung... ————————————————————————— Monkey Spiece:Monkey; Sex:female I am breathing with lung... I am running with two legs, sometimes with four legs... ————————————————————————— Fish I am breathing with lung... ————————————————————————— Fish Spiece:Fish; Sex:male I am breathing with cheek... I am running in the water with fins... ————————————————————————— Monkey Spiece:Monkey; Sex:female I am breathing with lung... I am running with two legs, sometimes with four legs... ————————————————————————— Monkey Spiece:Monkey; Sex:male I am breathing with lung... I am running with two legs, sometimes with four legs... I am climbing tree...
*多重繼承
類和接口都可以繼承接口,而且可以繼承不止一個接口。
需求:
IDraw接口,定義DrawLine、DrawCircle和DrawRectangle方法;
Drawer,定義為抽象類,實現(xiàn)IDraw接口,附加屬性Name;
ImpressionistDrawer(印象畫派畫家)類,繼承Drawer抽象類;
RealismDrawer(寫實主義畫派畫家)類,繼承Drawer抽象類。
如此,代碼如下:
public interface IDraw { void DrawLine(); void DrawCircle(); void DrawRectangle(); }
public abstract class Drawer : IDraw { private string _name; public Drawer(string name) { this._name = name; } public string Name { get { return this._name; } } public abstract void DrawLine(); public abstract void DrawCircle(); public abstract void DrawRectangle(); }
//印象畫派畫家 public class ImpressionistDrawer : Drawer { public ImpressionistDrawer(string name) : base(name) { } public override void DrawLine() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a line with pen.", this.Name)); } public override void DrawCircle() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a circle with pen.", this.Name)); } public override void DrawRectangle() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a rectangle with pen.", this.Name)); } }
//寫實主義畫派畫家 public class RealismDrawer : Drawer { public RealismDrawer(string name) : base(name) { } public override void DrawLine() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a line with pencil.", this.Name)); } public override void DrawCircle() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a circle with pencil.", this.Name)); } public override void DrawRectangle() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a rectangle with pencil.", this.Name)); } }
調(diào)用:
static void Main(string[] args) { IDraw draw001 = new RealismDrawer("莫柰"); draw001.DrawCircle(); draw001.DrawLine(); draw001.DrawRectangle(); Console.WriteLine(); IDraw draw002 = new ImpressionistDrawer("弗洛伊德"); draw002.DrawCircle(); draw002.DrawLine(); draw002.DrawRectangle(); Console.ReadLine(); }
運行結(jié)果:
The realism drawer:莫柰 is drawing a circle with pencil.
The realism drawer:莫柰 is drawing a line with pencil.
The realism drawer:莫柰 is drawing a rectangle with pencil.
The impressionist drawer:弗洛伊德 is drawing a circle with pen.
The impressionist drawer:弗洛伊德 is drawing a line with pen.
The impressionist drawer:弗洛伊德 is drawing a rectangle with pen.
擴展一下,比方說:這些畫家除了要畫畫之外,一樣都要吃飯睡覺打豆豆,怎么處理呢?
我們當然不能把吃飯睡覺打豆豆歸為IDraw這個intercace里面,因為這完全是不相干的行為呀!于是,我們考慮新建一個interface
public interface ILive { void EatRice(); void Sleep(); void BeatDouDou(); }
public abstract class Drawer : IDraw, ILive { private string _name; public Drawer(string name) { this._name = name; } #region IDraw public string Name { get { return this._name; } } public abstract void DrawLine(); public abstract void DrawCircle(); public abstract void DrawRectangle(); #endregion #region ILive public abstract void EatRice(); public abstract void Sleep(); public abstract void BeatDouDou(); #endregion }
public ImpressionistDrawer(string name) : base(name) { } public override void DrawLine() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a line with pen.", this.Name)); } public override void DrawCircle() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a circle with pen.", this.Name)); } public override void DrawRectangle() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a rectangle with pen.", this.Name)); } public override void EatRice() { Console.WriteLine(string.Format("The impressionist drawer:{0} is eating rice.", this.Name)); } public override void Sleep() { Console.WriteLine(string.Format("The impressionist drawer:{0} is sleeping.", this.Name)); } public override void BeatDouDou() { Console.WriteLine(string.Format("The impressionist drawer:{0} is beating DouDou.", this.Name)); } }
public class RealismDrawer : Drawer { public RealismDrawer(string name) : base(name) { } public override void DrawLine() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a line with pencil.", this.Name)); } public override void DrawCircle() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a circle with pencil.", this.Name)); } public override void DrawRectangle() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a rectangle with pencil.", this.Name)); } public override void EatRice() { Console.WriteLine(string.Format("The realism drawer:{0} is eating rice.", this.Name)); } public override void Sleep() { Console.WriteLine(string.Format("The realism drawer:{0} is sleeping.", this.Name)); } public override void BeatDouDou() { Console.WriteLine(string.Format("The realism drawer:{0} is beating DouDou.", this.Name)); } }
調(diào)用:
static void Main(string[] args) { IDraw drawer001 = new RealismDrawer("莫柰"); drawer001.DrawCircle(); drawer001.DrawLine(); drawer001.DrawRectangle(); Console.WriteLine(); IDraw drawer002 = new ImpressionistDrawer("弗洛伊德"); drawer002.DrawCircle(); drawer002.DrawLine(); drawer002.DrawRectangle(); Console.WriteLine(); ILive drawer003 = new RealismDrawer("莫柰"); drawer003.EatRice(); drawer003.Sleep(); drawer003.BeatDouDou(); Console.WriteLine(); ILive drawer004 = new RealismDrawer("弗洛伊德"); drawer004.EatRice(); drawer004.Sleep(); drawer004.BeatDouDou(); Console.ReadLine(); }
運行結(jié)果:
The realism drawer:莫柰 is drawing a circle with pencil. The realism drawer:莫柰 is drawing a line with pencil. The realism drawer:莫柰 is drawing a rectangle with pencil. The impressionist drawer:弗洛伊德 is drawing a circle with pen. The impressionist drawer:弗洛伊德 is drawing a line with pen. The impressionist drawer:弗洛伊德 is drawing a rectangle with pen. The realism drawer:莫柰 is eating rice. The realism drawer:莫柰 is sleeping. The realism drawer:莫柰 is beating DouDou. The realism drawer:弗洛伊德 is eating rice. The realism drawer:弗洛伊德 is sleeping. The realism drawer:弗洛伊德 is beating DouDou.