方法擦除:为什么说派生的class方法隐藏了基础class方法,但反过来呢?

Method erasure: why is it said that the the derived class method hides the base class, but it works the other way around?

class Animal
{
    public void Foo() { Console.WriteLine("Animal::Foo()"); }
}

class Cat : Animal
{
    public void Foo() { Console.WriteLine("Cat::Foo()"); }
}

class Test
{
    static void Main(string[] args)
    {
        Animal a;

        a = new Cat();
        a.Foo();  // output --> "Animal::Foo()"
    }
}

编译器警告说:

Cat.Foo hides the inherited member

然而输出实际上是来自基础 class。所以对我来说似乎是相反的,我调用的那个被基地 class.

中的那个隐藏了

如果您希望以这种方式使用,那么派生的 class 中的方法应该是 Overrided。检查 Virtual and also Override

This 可能对你有帮助。

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

class Cat : Animal
{
    public override void Foo() { Console.WriteLine("Cat::Foo()"); }
}

class Test
{
    static void Main(string[] args)
    {
        Animal a;

        a = new Cat();
        a.Foo();  // output --> "Cat::Foo()"
    }
}

您的程序的输出是 FooAnimal class 实现,因为引用的类型是 Animal 而不是 Cat

如果引用的类型为 Cat,输出将为 "Cat::Foo()"

Catclass的Foo方法隐藏了Animalclass的Foo方法,因为baseclasses 不能也不应该知道它们派生的 classes,而派生的 classes 是而且必须知道它们的基础 classes.

要故意隐藏基数 class 的成员,请使用 new 修饰符。这将告诉编译器隐藏是故意的,并且会抑制警告。

这是因为引用 a 是 Animal 类型。当您使用 Animal 类型的引用时,编译器会假定您想要获得 Animal 行为。覆盖虚方法很好,但是如果你真的隐藏了一个方法,那么你必须显式地使用隐藏class类型的引用来达到隐藏方法。

Cat c = new Cat();
Animal a = c; // note: a and c refer to the same object

a.Foo(); // output --> "Animal::Foo()"
c.Foo(); // output --> "Cat::Foo()"

从例子中可以看出,当涉及到隐藏时,结果取决于引用类型,而不是对象类型。

这是 polymorphism,这意味着能够为派生的 classes 重新定义方法。你必须在 base class 中将 Foo() 标记为虚拟,在 sub class 中将其标记为 override,如下所示:

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

class Cat : Animal
{
    public override void Foo() { Console.WriteLine("Cat::Foo()"); }
}

class Test
{
    static void Main(string[] args)
    {
        Animal a;

        a = new Cat();
        a.Foo();  // output --> "Cat::Foo()"
    }
}

在这种情况下 Foo() 具有多态行为!