多态性/重写

时间:2012-01-11 23:32:01

标签: c# .net oop inheritance polymorphism

有人可以解释这两个例子之间的区别吗?

  

A类

     

protected virtual string GetData()

     

B类

     

private override string GetData()

以下内容:

  

A类

     

protected string GetData()

     

B类

     

private string GetData()

假设'B级'继承自'A级'。

我总是假设你需要在超类中使用virtual而在子类中使用override如果你想要覆盖一个方法,但我尝试删除关键字并编译好的程序。究竟有什么区别?如果有的话?

3 个答案:

答案 0 :(得分:5)

您展示的第二个示例隐藏了父级的GetData,它不会覆盖它。

示例:

private class Base
{
    public virtual void Test()
    {
        Console.WriteLine("Base");
    }

    public void Test2()
    {
        Console.WriteLine("Base");
    }
}

private class Derived : Base
{
    public override void Test()
    {
        Console.WriteLine("Derived");
    }

    public void Test2()
    {
        Console.WriteLine("Derived");
    }
}

static void Main()
{
    Base b = new Base();
    Derived d = new Derived();
    Base dInB = new Derived();

    b.Test();
    d.Test();
    dInB.Test();

    b.Test2();
    d.Test2();
    dInB.Test2();

    Console.ReadKey(true);
}

输出:

Base    // Base.Test()
Derived // Derived.Test()
Derived // Derived.Test()
Base    // Base.Test2()
Derived // Derived.Test2()
Base    // You think you're calling Derived.Test2(), but you actually call Base.Test2()

实际上此示例无效,因为它应该使用Derived类中new中的public new void Test2()关键字。

它就像运算符重载一样工作。它实际上并没有覆盖任何东西。如果您具有确切类型Derived,则会调用新方法。

你必须非常小心隐藏成员,这完全不像重写(类)或实现(接口)。只有当您拥有 完全 类型时,才会调用 new 方法,否则仍然会调用基类型的方法!

答案 1 :(得分:3)

不同之处在于,在第一种情况下,你要覆盖,在第二种情况下,你隐藏的是完全不同的。

在第一种情况下:

class B: A
{
    void Foo()
    {
        B b = new B();
        A a = b;

        a.GetData() //B's GetData() will be called
        b.GetData() //B's GetData() will be called
    }
}

另一方面,在第二种情况下:

class B: A
{
    void Foo()
    {
        B b = new B();
        A a = b;

        a.GetData() //A's GetData() will be called
        b.GetData() //B's GetData() will be called
    }
}

在第二种情况下,您只是隐藏A的GetData()实现,但即使变量引用类型B的实例,您也始终能够通过变量类型A调用A的实现。请注意,这是完全不同的从最重要的行为来看。

答案 2 :(得分:0)

public class A
{
    public virtual string GetData() { return "A";}
}

public class B : A
{
    public override string GetData() { return "B"; }
}

如果您使用以下代码块中的类,您会期望什么?

        A a = new A();
        B b = new B();
        A c = new B();

        Console.WriteLine(a.GetData());
        Console.WriteLine(b.GetData());
        Console.WriteLine(c.GetData());

这将打印“A”“B”“B”。变量c存储为A类型,但在执行该方法时,代码被解析为“真实”实现。 (请参阅谷歌的虚拟功能表和解决原则)

如果您不使用下面的代码中的虚拟和覆盖,则会打印“A”“B”“A”。

public class A
{
    public string GetData() { return "A";}
}

public class B : A
{
    public new string GetData() { return "B"; }
}