簡體   English   中英

C#多態性的概念

[英]Concept of C# polymorphism

下面的代碼:

 public class Program
    {
        static void Main(string[] args)
        {
            father f = new son(); Console.WriteLine(f.GetType());
            f.show();
         }
    }

    public class father
    {
      virtual public void show()
        {
            Console.WriteLine("father");
        }
    }

    public class son : father
    {
        public override void  show()
        {
            Console.WriteLine("son");
        }
    }

結果是“兒子”。
如果我將“ public override void show() ”修改為“ public new void show() ”,則結果為“父親”。

因此,我總結出以下“規則”:

  • 使用“覆蓋”,將在運行時確定將調用哪個函數。 程序將根據當前對象的實際類型選擇合適的函數(如上所述,f的運行時類型為son,因此將其稱為son的show。)
  • 使用'new'修飾符,將在編譯時確定要調用的函數。程序將選擇對象的聲明類型來調用其函數。(如上所述,f的聲明類型為父親,因此使用'new'修飾符使輸出以顯示“父親”。

以上是我對多態性的理解,是否有誤解和錯誤?

使用'new'修飾符,將在編譯時確定要調用的函數。程序將選擇對象的聲明類型來調用其函數。(如上所述,f的聲明類型為父親,因此使用'new'修飾符使輸出以顯示“父親”。

並不是的。 這一決定仍然在執行時做,但new方法不會覆蓋在基類中的虛方法。 通過稍微擴展示例,可以很容易地看出這一點:

using System;

class Base
{
    public virtual void Foo()
    {
        Console.WriteLine("Base.Foo");
    }
}

class Derived : Base
{
    public override void Foo()
    {
        Console.WriteLine("Derived.Foo");
    }
}

class MoreDerived : Derived
{
    public new void Foo()
    {
        Console.WriteLine("MoreDerived.Foo");
    }
}

class Test
{
    static void Main()
    {
        Base x = new MoreDerived();
        x.Foo(); // Prints Derived.Foo
    }
}

在這里,在編譯時決定調用Base.Foo的最重要的實現-例如,如果有多個Foo簽名,則將決定使用哪個簽名。 當然,目前尚不知道哪個實現是“最重要的”。

執行時 ,CLR將根據目標對象的實際類型( MoreDerived找到最被重寫的實現。 但是MoreDerived.Foo不會覆蓋Base.Foo ...,而Derived.Foo可以,因此Derived的實現是實際執行的。

是的,它的工作原理是……您的理解是正確的。

但是對於第二種情況,當您使用override new索引時,它將隱藏實際的實現,即父類實現

由於使用new關鍵字定義此方法,因此不調用派生類方法-而是調用基類方法。

來自MSDN的示例

// Define the base class
class Car
{
    public virtual void DescribeCar()
    {
        System.Console.WriteLine("Four wheels and an engine.");
    }
}

// Define the derived classes
class ConvertibleCar : Car
{
    public new virtual void DescribeCar()
    {
        base.DescribeCar();
        System.Console.WriteLine("A roof that opens up.");
    }
}

class Minivan : Car
{
    public override void DescribeCar()
    {
        base.DescribeCar();
        System.Console.WriteLine("Carries seven people.");
    }
}

上課

Car[] cars = new Car[3];
cars[0] = new Car();
cars[1] = new ConvertibleCar();
cars[2] = new Minivan();

輸出

Car object: YourApplication.Car
Four wheels and an engine.
----------
Car object: YourApplication.ConvertibleCar
Four wheels and an engine.
----------
Car object: YourApplication.Minivan
Four wheels and an engine.
Carries seven people.
----------

MSDN就是一個很好的例子: 知道何時使用覆蓋和新關鍵字(C#編程指南)

使用'new'修飾符,將在編譯時確定要調用的函數。程序將選擇對象的聲明類型來調用其函數。(如上所述,f的聲明類型為父親,因此使用'new'修飾符使輸出以顯示“父親”。

這有點不對。 使用new表示此函數不會覆蓋基類的任何函數。 函數分派仍然在運行時發生,但是不考慮該函數。 如果您有“孫子”或“女兒”課程來測試更多內容,則區別會更加明顯。

通過類的類型調用普通方法,通過分配給對象的內存內容調用虛擬方法。 現在,關鍵字new隱藏了多態的概念,只關心其類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM