繁体   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