c#多态性的概念

本文关键字:多态性 | 更新日期: 2023-09-27 17:53:57

下面代码:

 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");
        }
    }

结果是'son'。
如果我将' public override void show() '修改为' public new void show() ',结果是'father'。

所以我总结如下'规则':

  • 使用'override',调用哪个函数是在运行时确定的时间。程序会根据。选择合适的功能当前对象的实际类型。(如上所述,f的运行时类型是son,所以它调用儿子的节目。)
  • 使用'new'修饰符,确定何时调用哪个函数它被编译。程序将选择对象声明的类型为调用它的函数。(如上所述,f的声明类型是father,所以使用'new'修饰符使输出显示'father'。

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

c#多态性的概念

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

没有。这个决定仍然是在执行时做出的,但是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中的实现才是实际执行的。

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

这有点错。使用new意味着这个函数不覆盖基类的任何函数。函数分派仍然在运行时发生,但不考虑此函数。如果您有孙子类或女儿类来进行更多的测试,那么差异将更加明显。

是的,它是这样工作的…你的理解是对的。

但对于第二种情况,当你使用new而不是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有很好的例子:知道何时使用覆盖和新关键字(c#编程指南)

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