国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

深入理解OOP(二):多態和繼承(繼承)

2019-11-14 13:36:02
字體:
來源:轉載
供稿:網友

本文是深入淺出OOP第二篇,主要說說繼承的話題。

  • 深入理解OOP(一):多態和繼承(初期綁定和編譯時多態)

  • 深入理解OOP(二):多態和繼承(繼承)

  • 深入理解OOP(三):多態和繼承(動態綁定和運行時多態)

  • 深入理解OOP(四):多態和繼承(C#中的抽象類)

  • 深入理解OOP(五):C#中的訪問修飾符(Public/PRivate/Protected/Internal/Sealed/Constants/Static and Readonly Fields)

  • 深入理解OOP(六):枚舉(實用方法)

  • 深入理解OOP(七):屬性(實用方法)

  • 深入理解OOP(八):索引器(實用方法)

  • 深入理解OOP(九):事件(深入理解)

 


繼承的實現

創建一個Console工程,命名為InheritanceAndPolymorphism。添加ClassA、ClassB類,并拷貝下面的代碼:

ClassA:   class ClassA     {             }ClassB:    class ClassB    {        public int x = 100;        public void Display1()        {            Console.WriteLine("ClassB Display1");        }        public void Display2()        {            Console.WriteLine("ClassB Display2");        }    }

 

在Program.cs中,調用ClassA

class Program    {        static void Main(string[] args)        {            ClassA a = new ClassA();            a.Display1();        }    }

如果運行,肯定會報錯的。

Error: 'InheritanceAndPolymorphism.ClassA' does not contain a definition for 'Display1' and no extension method 'Display1' accepting a first argument of type 'InheritanceAndPolymorphism.ClassA' could be found

因為我們在ClassA中未定義Display1的方法。 下面我們重寫,使ClassA繼承自ClassB。

 

ClassA:  class ClassA:ClassB    {            }ClassB:class ClassB    {        public int x = 100;        public void Display1()        {            Console.WriteLine("ClassB Display1");        }        public void Display2()        {            Console.WriteLine("ClassB Display2");        }    }

 

再次運行,結果如下:

ClassB Display1

ClassA已經可以訪問其基類的Display1函數了,這個簡單的實例說明了繼承可復用基類的妙處,下面這張圖以父子財產繼承關系說明了繼承的意義。

 

再來看另外一個場景,假設ClassA也有一個Display1函數,簽名和其基類一樣的:

class ClassA:ClassB    {        public void Display1()        {            System.Console.WriteLine("ClassA Display1");        }    }ClassB:class ClassB    {        public int x = 100;        public void Display1()        {            Console.WriteLine("ClassB Display1");        }        public void Display2()        {            Console.WriteLine("ClassB Display2");        }    }

執行后結果如下:

ClassA Display1

看起來結果是對的,ClassA默認調用了自己的Display1函數,但是Visual Studio有一個警告:

Warning: 'InheritanceAndPolymorphism.ClassA.Display1()' hides inherited member 'InheritanceAndPolymorphism.ClassB.Display1()'. Use the new keyWord if hiding was intended.

C#中對方法的調用首先是查詢ClassA自己中有無Display1函數,再查詢其基類有無Display1函數。在基類和子類出現同樣函數的情況現實項目中是存在的,可能是基類代碼過于陳舊了,子類既想用同簽名的函數,又無法停止基類的同簽名函數,故會出現這樣的警告---盡管邏輯正確,但是這種設計還是有一些瑕疵的。

 

我們再試試在CalssA中通過base調用基類同名方法的情況:

 

ClassA:  class ClassA:ClassB    {        public void Display1()        {            Console.WriteLine("ClassA Display1");            base.Display1();        }    }ClassB:class ClassB    {        public int x = 100;        public void Display1()        {            Console.WriteLine("ClassB Display1");        }        public void Display2()        {            Console.WriteLine("ClassB Display2");        }    }

執行結果如下:

ClassA Display1

ClassB Display1

這個實驗說明C#提供了base關鍵詞,用于在繼承中子類調用基類的函數或者變量(非private類型)。

 

同樣的,在ClassA.Display1中調用其基類的Display2也是可以的,代碼如下所示:

/// <summary>   /// ClassB: acting as base class    /// </summary>   class ClassB    {        public int x = 100;        public void Display1()        {            Console.WriteLine("ClassB Display1");        }        public void Display2()        {            Console.WriteLine("ClassB Display2");        }    }    /// <summary>    /// ClassA: acting as derived class    /// </summary>    class ClassA : ClassB    {        public void Display1()        {            Console.WriteLine("ClassA Display1");            base.Display2();        }    }    /// <summary>    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>    class Program    {        static void Main(string[] args)        {            ClassA a = new ClassA();            a.Display1();            Console.ReadKey();        }    }

執行結果如下:

ClassA Display1

ClassB Display2

 

那么可否通過基類調用其子類的函數呢?

/// <summary>   /// ClassB: acting as base class    /// </summary>   class ClassB    {        public int x = 100;        public void Display1()        {            Console.WriteLine("ClassB Display1");        }    }    /// <summary>    /// ClassA: acting as derived class    /// </summary>    class ClassA : ClassB    {        public void Display2()        {            Console.WriteLine("ClassA Display2");        }    }    /// <summary>    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>    class Program    {        static void Main(string[] args)        {            ClassB b = new ClassB();            b.Display2();            Console.ReadKey();        }    }

運行報錯:

Error: 'InheritanceAndPolymorphism.ClassB' does not contain a definition for 'Display2' and no extension method 'Display2' accepting a first argument of type 'InheritanceAndPolymorphism.ClassB' could be found

原因是繼承無法實現逆向調用,既基類無法調用子類。

 

除了構造函數和析構函數,子類繼承了其基類的一些(包括private的成員變量和成員函數,只是無法訪問)。

 

在C#中,一個類默認繼承的是object類型,object是C#所有引用類型的基類;同時,繼承具有傳遞性,如ClassC繼承自ClassB,ClassB繼承自ClassA,則ClassC可完全復用ClassA的數據和函數---ClassC繼承了ClassA。

 

C#中所有的類型都可被繼承嗎?

public class ClassW : System.ValueType   {   }   public class ClassX : System.Enum   {   }   public class ClassY : System.Delegate   {   }   public class ClassZ : System.Array   {   }

執行結果:

'InheritanceAndPolymorphism.ClassW' cannot derive from special class 'System.ValueType'

'InheritanceAndPolymorphism.ClassX' cannot derive from special class 'System.Enum'

'InheritanceAndPolymorphism.ClassY' cannot derive from special class 'System.Delegate'

'InheritanceAndPolymorphism.ClassZ' cannot derive from special class 'System.Array'

運行的結果讓人抓狂

 

在C#中,自定義類無法繼承自C#內置的一些類,如System.ValueTypeSystem.EnumSystem.DelegateSystem.Array, etc。

 

下面這個例子我們再看看C++中的多類繼承是否可在C#中實現:

 public class ClassW { } public class ClassX { } public class ClassY : ClassW, ClassX { }

執行結果:

Compile time Error: Class 'InheritanceAndPolymorphism.ClassY' cannot have multiple base classes: 'InheritanceAndPolymorphism.ClassW' and 'ClassX'.

 執行結論是:C#僅支持單類繼承,不支持C++的這種星型繼承關系。 要使用星型繼承關系,請用接口實現。

 

那么可否實現循環依賴繼承呢?

public class ClassW: ClassY    {    }    public class ClassX: ClassW    {    }    public class ClassY :  ClassX    {    }

代碼邏輯很簡單,ClassW繼承自ClassY,ClassX繼承自ClassW, ClassY繼承自ClassX。

但是編譯后報錯了:

Error: Circular base class dependency involving 'InheritanceAndPolymorphism.ClassX' and 'InheritanceAndPolymorphism.ClassW'.

我們得出一個結論,C#中不許環形依賴繼承。

實例對象的是否可賦值

ClassB:public class ClassB    {        public int b = 100;    }ClassA:    public class ClassA    {        public int a = 100;    }

Program.cs 代碼如下

public class Program    {        private static void Main(string[] args)        {            ClassB classB = new ClassB();            ClassA classA = new ClassA();            classA = classB;            classB = classA;        }    }

我們嘗試判斷ClassA、ClassB的對象是否可賦值。

編譯的結果是:報錯了

Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA' Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassA' to 'InheritanceAndPolymorphism.ClassB'

盡管ClassA和ClassB里面的數據成員變量a數據一致,都為100,但是這里用等號比較的是類型--引用地址,故無法進行賦值。

 

我們再來試試繼承關系的:

public class ClassB    {        public int b = 100;    }    public class ClassA:ClassB    {        public int a = 100;    }    /// <summary>    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>    public class Program    {        private static void Main(string[] args)        {            ClassB classB = new ClassB();            ClassA classA = new ClassA();            classA = classB;            classB = classA;        }    }

ClassA繼承自ClassB,我們希望可以直接賦值其實例對象。

運行結果如下:

Error: Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA'.

運行結論:C#中子類對象可直接賦值給基類對象,基類對象需要往下強轉。代碼修改如下:

public class ClassB    {        public int b = 100;    }    public class ClassA:ClassB    {        public int a = 100;    }    /// <summary>    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>    public class Program    {        private static void Main(string[] args)        {            ClassB classB = new ClassB();            ClassA classA = new ClassA();            classB=classA;            classA = (ClassA)classB;        }    }

這樣編譯就通過了。

如果ClassA不繼承自ClassB,則這種強轉在C#中是會報錯的:

Cannot convert type 'InheritanceAndPolymorphism.ClassA' to 'InheritanceAndPolymorphism.ClassB'

Cannot convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA'

本節結論

  • 無法阻止子類覆蓋基類同簽名方法
  • 繼承關系是子類的同簽名方法先查找,再查找其基類的
  • base關鍵字被C#用于在子類中調用基類函數、變量
  • 繼承關系不可逆轉
  • 除了構造函數、析構函數,子類繼承了基類的一些
  • 自定義類默認繼承自Object類型,但是C#的這些類型不能被繼承:System.ValueTypeSystem.EnumSystem.DelegateSystem.Array, etc.
  • C#不支持從多類繼承
  • C#不支持循環繼承
  • 子類對象可直接賦值給基類,反之需要強轉

 

譯文地址:http://www.survivalescaperooms.com/powertoolsteam/p/Diving-in-OOP-Polymorphism-and-Inheritance-Part.html

原文地址:Diving in OOP (Day 2): Polymorphism and Inheritance (Inheritance)

 

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宜兴市| 营口市| 嘉鱼县| 左权县| 西平县| 祥云县| 保靖县| 宁陵县| 乌拉特前旗| 遵化市| 武宣县| 张北县| 唐河县| 喜德县| 娄烦县| 章丘市| 成安县| 马公市| 屯留县| 金昌市| 大城县| 甘肃省| 黑山县| 张家港市| 东港市| 田林县| 紫金县| 文登市| 虹口区| 汪清县| 开平市| 长治县| 扶余县| 封丘县| 牙克石市| 永吉县| 启东市| 尼玛县| 潜江市| 临朐县| 新邵县|