91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

深入淺出OOP(三): 多態和繼承(動態綁定/運行時多態)

發布時間:2020-09-01 08:50:49 來源:網絡 閱讀:451 作者:powertoolsteam 欄目:編程語言

在前面的文章中,我們介紹了編譯期多態、params關鍵字、實例化、base關鍵字等。本節我們來關注另外一種多態:運行時多態, 運行時多態也叫遲綁定。

 

運行時多態或遲綁定、動態綁定

在C#語音中,運行時多態也叫方法重寫(overriding),我們可以在子類中overriding基類的同簽名函數,使用“virtual & override”關鍵字即可。

 

C#的New、Override關鍵字

深入淺出OOP(三): 多態和繼承(動態綁定/運行時多態)

創建一個console 示例工程,命名為InheritanceAndPolymorphism。在Program.cs基礎上,再添加2個類文件,分別命名為ClassA.cs、ClassB.cs。拷貝如下代碼:

public class ClassA
    {        public void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }        public void BBB()
        {
            Console.WriteLine("ClassA BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassA CCC");
        }
    }

 

ClassB:

public class ClassB
    {        public void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }        public void BBB()
        {
            Console.WriteLine("ClassB BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassB CCC");
        }
    }

在上面的代碼中,我們可以看到ClassA、ClassB有同樣簽名的方法,可以在program.cs中直接使用。

我們對代碼再做休整,結構如下:

/// <summary>
    /// ClassB, acting as a base class    /// </summary>
    public class ClassB
    {        public void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }        public void BBB()
        {
            Console.WriteLine("ClassB BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassB CCC");
        }
    }    /// <summary>
    /// Class A, acting as a derived class    /// </summary>
    public class ClassA : ClassB
    {        public void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }        public void BBB()
        {
            Console.WriteLine("ClassA BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassA CCC");
        }
    }

 

Program.cs

    /// <summary>
    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>
    public class Program
    {        private static void Main(string[] args)
        {
            ClassA x = new ClassA();
            ClassB y=new ClassB();
            ClassB z=new ClassA();

            x.AAA(); x.BBB(); x.CCC();
            y.AAA(); y.BBB();y.CCC();
            z.AAA(); z.BBB(); z.CCC();
        }
    }

F5,運行代碼,結果如下:

ClassA AAA

ClassA BBB

ClassA CCC

ClassB AAA

ClassB BBB

ClassB CCC

ClassB AAA

ClassB BBB

ClassB CCC

但同時,在VS的Output窗口,我們獲得了3個Warnings:

'InheritanceAndPolymorphism.ClassA.AAA()' hides inherited member

'InheritanceAndPolymorphism.ClassB.AAA()'. Use the new keyword if hiding was intended.

'InheritanceAndPolymorphism.ClassA.BBB()' hides inherited member

'InheritanceAndPolymorphism.ClassB.BBB()'. Use the new keyword if hiding was intended.

'InheritanceAndPolymorphism.ClassA.CCC()' hides inherited member

'InheritanceAndPolymorphism.ClassB.CCC()'. Use the new keyword if hiding was intended.

這些Warnings的原因是因為子類和基類的AAA、BBB、CCC方法簽名相同,盡管從執行上看優先執行子類同簽名的方法,但是可能會有潛在的問題,故Warnings提出。

 

重構實驗

基于上面的Warning,我們手動修改代碼,看看如何消除這些Warnings。

先給子類添加new、override關鍵字試試:

/// <summary>
    /// Class A, acting as a derived class    /// </summary>
    public class ClassA : ClassB
    {        public override void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }        public new void BBB()
        {
            Console.WriteLine("ClassA BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassA CCC");
        }
    }

 

執行的結果是報錯了:

Error: 'InheritanceAndPolymorphism.ClassA.AAA()': cannot override inherited member 'InheritanceAndPolymorphism.ClassB.AAA()' because it is not marked virtual, abstract, or override

 

深入淺出OOP(三): 多態和繼承(動態綁定/運行時多態)

從這個錯誤提示信息看,我們需要修改基類方法,如添加virtual關鍵字。

/// <summary>
    /// ClassB, acting as a base class    /// </summary>
    public class ClassB
    {        public virtual void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }        public virtual void BBB()
        {
            Console.WriteLine("ClassB BBB");
        }        public virtual void CCC()
        {
            Console.WriteLine("ClassB CCC");
        }
    }    /// <summary>
    /// Class A, acting as a derived class    /// </summary>
    public class ClassA : ClassB
    {        public override void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }        public new void BBB()
        {
            Console.WriteLine("ClassA BBB");
        }        public void CCC()
        {
            Console.WriteLine("ClassA CCC");
        }
    }    /// <summary>
    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>
    public class Program
    {        private static void Main(string[] args)
        {
            ClassB y = new ClassB();
            ClassA x = new ClassA();
            ClassB z = new ClassA();

            y.AAA(); y.BBB(); y.CCC();
            x.AAA(); x.BBB(); x.CCC();
            z.AAA(); z.BBB(); z.CCC();

            Console.ReadKey();
        }
    }

執行,則無Warning了,通過這個實例,我們得知通過在基類添加Virtual關鍵字授權其子類可override基類同簽名方法的權限,方便了OOP的擴展。

 

3個類的運行時多態

ClassA\ClassB基礎上,下面添加ClassC,看看3個類繼承關系的運行時多態:

/// <summary>
    /// ClassB, acting as a base class    /// </summary>
    public class ClassB
    {        public  void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }        public virtual void BBB()
        {
            Console.WriteLine("ClassB BBB");
        }        public virtual void CCC()
        {
            Console.WriteLine("ClassB CCC");
        }
    }    /// <summary>
    /// Class A, acting as a derived class    /// </summary>
    public class ClassA : ClassB
    {        public virtual void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }        public new void BBB()
        {
            Console.WriteLine("ClassA BBB");
        }        public override void CCC()
        {
            Console.WriteLine("ClassA CCC");
        }
    }    /// <summary>
    /// Class C, acting as a derived class    /// </summary>
    public class ClassC : ClassA
    {        public override void AAA()
        {
            Console.WriteLine("ClassC AAA");
        }        public void CCC()
        {
            Console.WriteLine("ClassC CCC");
        }
    }    /// <summary>
    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>
    public class Program
    {        private static void Main(string[] args)
        {
            ClassB y = new ClassA();
            ClassB x = new ClassC();
            ClassA z = new ClassC();

            y.AAA(); y.BBB(); y.CCC();
            x.AAA(); x.BBB(); x.CCC();
            z.AAA(); z.BBB(); z.CCC();

            Console.ReadKey();
        }
    }

運行結果:

ClassB AAA

ClassB BBB

ClassA CCC

ClassB AAA

ClassB BBB

ClassA CCC

ClassC AAA

ClassA BBB

ClassA CCC

如果基類聲明了virtual 關鍵字,子類可使用override修飾符實現運行時多態:只有在編譯器動態決定是否被調用。

如果未標明virtual或非virtual,則方法是否被調用在編譯期就能決定。

 

深入淺出OOP(三): 多態和繼承(動態綁定/運行時多態)

 

再看看下面的例子:

internal class A
    {        public virtual void X()
        {
        }
    }    internal class B : A
    {        public new void X()
        {
        }
    }    internal class C : B
    {        public override void X()
        {
        }
    }

F5運行,結果報錯了:

Error: 'InheritanceAndPolymorphism.C.X()': cannot override inherited member 'InheritanceAndPolymorphism.B.X()' because it is not marked virtual, abstract, or override

錯誤的原因是A中定義了virtual的X函數,在B中用new關鍵字隱藏了A中的X函數。當C嘗試通過override關鍵字的時候,是獲得不了A中的virtual關鍵字X函數的,既在C中X函數為非Virtual的,故不能override。

 

切斷關系

internal class A
    {        public virtual void X()
        {
            Console.WriteLine("Class: A ; Method X");
        }
    }    internal class B : A
    {        public new virtual void X()
        {
            Console.WriteLine("Class: B ; Method X");
        }
    }    internal class C : B
    {        public override void X()
        {
            Console.WriteLine("Class: C ; Method X");
        }
    }    /// <summary>
    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>
    public class Program
    {        private static void Main(string[] args)
        {
            A a = new C();
            a.X();
            B b = new C();
            b.X();

            Console.ReadKey();
        }
    }

執行結果如下:

Class: A ; Method X
Class: C ; Method X

深入淺出OOP(三): 多態和繼承(動態綁定/運行時多態)

在這里,我們通過在B類中添加new Virtual修飾符,然后在C中即可使用B中Virtual的X函數了。

 

4個類的運行時多態

深入淺出OOP(三): 多態和繼承(動態綁定/運行時多態)

在上面繼承上,在運行時多態中添加第四個類:ClassD。

/// <summary>
    /// Class A    /// </summary>
    public class ClassA
    {        public virtual void XXX()
        {
            Console.WriteLine("ClassA XXX");
        }
    }    /// <summary>
    /// ClassB    /// </summary>
    public class ClassB:ClassA 
    {        public override void XXX()
        {
            Console.WriteLine("ClassB XXX");
        }
    }    /// <summary>
    /// Class C    /// </summary>
    public class ClassC : ClassB
    {        public virtual new void XXX()
        {
            Console.WriteLine("ClassC XXX");
        }
    }    /// <summary>
    /// Class D    /// </summary>
    public class ClassD : ClassC
    {        public override void XXX()
        {
            Console.WriteLine("ClassD XXX");
        }
    }    /// <summary>
    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>
    public class Program
    {        private static void Main(string[] args)
        {
            ClassA a = new ClassD();
            ClassB b = new ClassD();
            ClassC c=new ClassD();
            ClassD d=new ClassD();
           
            a.XXX();
            b.XXX();
            c.XXX();
            d.XXX();

            Console.ReadKey();
        }
    }

 

執行結果如下:

ClassB XXX

ClassB XXX

ClassD XXX

ClassD XXX

第一行輸出中,來自a.XXX()函數 , 我們在 ClassA中定義了XXX函數,然后在ClassB中使用new關鍵字切斷了virtual關系--對子類而言。因此XXX函數從ClassC開始成為新的virtual函數,在這個代碼中a是ClassD的實例,但是聲明的為ClassA,故從下往上找,找到ClassB的XXX函數,打印并輸出結果。

 

永無止境的循環

 

/// <summary>
    /// Class A    /// </summary>
    public class ClassA
    {        public virtual void XXX()
        {
            Console.WriteLine("ClassA XXX");
        }
    }    /// <summary>
    /// ClassB    /// </summary>
    public class ClassB:ClassA 
    {        public override void XXX()
        {
            ((ClassA)this).XXX();
            Console.WriteLine("ClassB XXX");
        }
    }   
    /// <summary>
    /// Program: used to execute the method.    /// Contains Main method.    /// </summary>
    public class Program
    {        private static void Main(string[] args)
        {
            ClassA a = new ClassB();
            a.XXX();
           
        }
    }

運行報錯:

Error: {Cannot evaluate expression because the current thread is in a stack overflow state.}

在這個例子中,((ClassA)this).XXX(); 導致了循環調用,修改為base.XXX即可修復這個強轉導致的循環調用。

 

結論

  • 在C#中,子類對象可賦值給一個基類對象;相反需要強轉。

  • override關鍵字用于子類重寫同簽名的基類virtual函數

  • 用new和override可重寫基類virtual的同簽名函數

  • virtual修飾符的函數,只能在運行時決定是否被執行

  • 函數未用virtual修飾,則在編譯期即可決定是否被調用

 

原文鏈接:Diving in OOP (Day 3): Polymorphism and Inheritance (Dynamic Binding/Run Time Polymorphism)


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

盘山县| 邻水| 景洪市| 宝应县| 长沙县| 射洪县| 临夏县| 中山市| 卫辉市| 集贤县| 华池县| 孟州市| 花莲县| 汶川县| 商丘市| 娄烦县| 桑植县| 怀来县| 临朐县| 民权县| 蓬安县| 白城市| 易门县| 乌审旗| 石门县| 合江县| 屏东县| 兴和县| 台南市| 黎城县| 扎赉特旗| 青田县| 金寨县| 高安市| 华蓥市| 从化市| 醴陵市| 杭州市| 澄迈县| 林甸县| 宜良县|