C#多态性的概念

时间:2013-01-16 07:15:00

标签: 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的运行时类型是儿子, 所以它叫儿子的节目。)
  • 使用'new'修饰符,将在何时确定将调用哪个函数 它被编译。程序将选择对象的声明类型 调用它的函数。(如上所述,f的声明类型是父,所以 使用'new'修饰符使输出显示'父'。

以上都是我对多态性的理解。任何误解和错误?

4 个答案:

答案 0 :(得分:5)

  

使用'new'修饰符,在编译时确定将调用哪个函数。程序将选择对象的声明类型来调用它的函数。(如上所述,f的声明类型是父,所以使用'new'修饰符使输出显示为“父亲”。

不是真的。仍然在执行时做出决定,但new方法 not 覆盖基类中的虚方法。通过稍微扩展您的示例可以很容易地显示出来:

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中的实现是实际执行的实现。

答案 1 :(得分:2)

是的,它的工作方式只是......你的理解是对的......

但对于使用new intad override的第二种情况,它隐藏了实际的实现,即父类实现

由于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有很好的例子:Knowing When to Use Override and New Keywords (C# Programming Guide)

答案 2 :(得分:2)

  

使用'new'修饰符,在编译时确定将调用哪个函数。程序将选择对象的声明类型来调用它的函数。(如上所述,f的声明类型是父,所以使用'new'修饰符使输出显示为“父亲”。

这有点不对劲。使用new意味着此函数不会覆盖基类的任何函数。函数调度仍然在运行时发生,但不考虑此函数。如果您有Grandson或Daughter类来测试更多,那么差异会更清楚。

答案 3 :(得分:1)

通过类的类型调用普通方法,并且通过分配给对象的内存的内容调用虚方法。现在关键字new隐藏了多态的概念,只关心它的类型。