溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

深入淺出OOP(二): 多態(tài)和繼承(繼承)

發(fā)布時間:2020-06-26 15:45:14 來源:網(wǎng)絡(luò) 閱讀:322 作者:powertoolsteam 欄目:編程語言

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

 

繼承的介紹

在OOP中,繼承有如下的定義:

  • 繼承是一種OOP的機(jī)制,用于派生繼承預(yù)定義的類

  • 在這個繼承關(guān)系中,預(yù)定義的類是基類,新類是子類

  • 繼承常常用于實(shí)現(xiàn)代碼重用

  • 繼承允許子類復(fù)用基類非private的的數(shù)據(jù)和方法

繼承的實(shí)現(xiàn)

創(chuàng)建一個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中,調(diào)用ClassA

class Program
    {        static void Main(string[] args)
        {

            ClassA a = new ClassA();
            a.Display1();
        }
    }

如果運(yùn)行,肯定會報錯的。

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

因?yàn)槲覀冊贑lassA中未定義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");
        }
    }

 

再次運(yùn)行,結(jié)果如下:

ClassB Display1

ClassA已經(jīng)可以訪問其基類的Display1函數(shù)了,這個簡單的實(shí)例說明了繼承可復(fù)用基類的妙處,下面這張圖以父子財產(chǎn)繼承關(guān)系說明了繼承的意義

深入淺出OOP(二): 多態(tài)和繼承(繼承)

 

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

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");
        }
    }

執(zhí)行后結(jié)果如下:

ClassA Display1

看起來結(jié)果是對的,ClassA默認(rèn)調(diào)用了自己的Display1函數(shù),但是Visual Studio有一個警告:

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

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

 

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

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");
        }
    }

 

執(zhí)行結(jié)果如下:

ClassA Display1

ClassB Display1

這個實(shí)驗(yàn)說明C#提供了base關(guān)鍵詞,用于在繼承中子類調(diào)用基類的函數(shù)或者變量(非private類型)。

 

深入淺出OOP(二): 多態(tài)和繼承(繼承)

 

同樣的,在ClassA.Display1中調(diào)用其基類的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();
        }
    }

 

執(zhí)行結(jié)果如下:

ClassA Display1

ClassB Display2

 

那么可否通過基類調(diào)用其子類的函數(shù)呢?

/// <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();
        }
    }

 

運(yùn)行報錯:

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

原因是繼承無法實(shí)現(xiàn)逆向調(diào)用,既基類無法調(diào)用子類。

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

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

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

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

執(zhí)行結(jié)果:

'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'

 

運(yùn)行的結(jié)果讓人抓狂

深入淺出OOP(二): 多態(tài)和繼承(繼承)

在C#中,自定義類無法繼承自C#內(nèi)置的一些類,如System.ValueType, System.Enum, System.Delegate, System.Array, etc。

 

下面這個例子我們再看看C++中的多類繼承是否可在C#中實(shí)現(xiàn):

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

執(zhí)行結(jié)果:

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

 

執(zhí)行結(jié)論是:C#僅支持單類繼承,不支持C++的這種星型繼承關(guān)系。 要使用星型繼承關(guān)系,請用接口實(shí)現(xiàn)。

 

那么可否實(shí)現(xiàn)循環(huán)依賴?yán)^承呢?

   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'.

深入淺出OOP(二): 多態(tài)和繼承(繼承)

 

我們得出一個結(jié)論,C#中不許環(huán)形依賴?yán)^承。

 

實(shí)例對象的是否可賦值
ClassB:public class ClassB
    {        public int b = 100;
    }

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

 

Program.cs 代碼如下

/// <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的對象是否可賦值。

編譯的結(jié)果是:報錯了

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

深入淺出OOP(二): 多態(tài)和繼承(繼承)

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

 

我們再來試試?yán)^承關(guān)系的:

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,我們希望可以直接賦值其實(shí)例對象。

 

運(yùn)行結(jié)果如下:

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

運(yùn)行結(jié)論:C#中子類對象可直接賦值給基類對象,基類對象需要往下強(qiáng)轉(zhuǎn)。代碼修改如下:

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,則這種強(qiáng)轉(zhuǎn)在C#中是會報錯的:

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

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

 

 

本節(jié)結(jié)論

  • 無法阻止子類覆蓋基類同簽名方法

  • 繼承關(guān)系是子類的同簽名方法先查找,再查找其基類的

  • base關(guān)鍵字被C#用于在子類中調(diào)用基類函數(shù)、變量

  • 繼承關(guān)系不可逆轉(zhuǎn)

  • 除了構(gòu)造函數(shù)、析構(gòu)函數(shù),子類繼承了基類的一些

  • 自定義類默認(rèn)繼承自O(shè)bject類型,但是C#的這些類型不能被繼承:System.ValueType, System.Enum, System.Delegate, System.Array, etc.

  • C#不支持從多類繼承

  • C#不支持循環(huán)繼承

  • 子類對象可直接賦值給基類,反之需要強(qiáng)轉(zhuǎn)

 

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


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI