0

下面的代码:

 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的声明类型是father,所以使用'new'修饰符使输出以显示“父亲”。

以上就是我对多态的理解。有什么误解和错误吗?

4

4 回答 4

5

使用'new'修饰符,在编译时决定调用哪个函数。程序会选择对象的声明类型来调用它的函数。(如上,f的声明类型是father,所以使用'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是实际执行的实现。

于 2013-01-16T07:25:47.450 回答
2

是的,它只是这样工作......你的理解是正确的......

但是对于第二种情况,当您使用new intadoverride时隐藏实际实现,即父类实现

由于使用 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)

于 2013-01-16T07:17:23.077 回答
2

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

这有点不对。Usingnew意味着这个函数不会覆盖基类的任何函数。函数调度仍然发生在运行时,但不考虑这个函数。如果您有 Grandson 或 Daughter 课程来测试更多,差异会更明显。

于 2013-01-16T07:18:32.330 回答
1

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

于 2013-01-16T07:25:28.863 回答