为什么我们使用虚拟和覆盖?

Rac*_*oon 15 c#

为什么我们使用override和virtual如果它们在我们不使用override和virtual时会产生相同的效果?

例1:

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

class DerivedClass : BaseClass
{
    public override string call()
    {
        return "B";
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:B

例2:

class BaseClass
{
    public string call()
    {
        return "A";
    }
}

class DerivedClass : BaseClass
{
    public string call()
    {
        return "B";
    }
}
Run Code Online (Sandbox Code Playgroud)

输出仍然是相同的:

输出:B

运行测试:

class Program
{
    static void Main(string[] args)
    {
        DerivedClass dc = new DerivedClass();
        Console.WriteLine(dc.call());
        Console.ReadKey();
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器是否在编译时自动添加虚拟和覆盖?

如果有人向我解释使用虚拟和覆盖的原因,我会很高兴.

Mar*_*ell 21

(注意,我正在悄悄忽略编译错误)

现在做:

BaseClass obj = new DerivedClass();
Console.WriteLine(obj.call());
Run Code Online (Sandbox Code Playgroud)

没有virtual,这将打印A,当实际上DerivedClass应该写B.这是因为它只是简单地调用了BaseClass实现(因为它obj被输入为BaseClass,并且没有定义多态).

  • @Vural因为*重要*.如果您没有使用多态,那么是:它们将显示相同的内容.不同之处在于`virtual`支持抽象和[替换](http://en.wikipedia.org/wiki/Liskov_substitution_principle).你问"为什么我们使用{这些}" - 我说:**支持这种情况**.很多时候,我们不知道具体/最终类型 - 我们只知道基类型.例如,winforms中的`Control`,或ASP.NET中的`Page`. (5认同)
  • @Vural非常仔细地看待我和你的场景之间的区别.现在将代码更改为`BaseClass bc = new DerivedClass(); Console.WriteLine(bc.call());`.要强调:没有***它不会在编译时自动添加它; 仅仅是,你正在测试不同的东西. (3认同)

Sal*_*iti 5

Virtual和override是面向对象编程中继承的基本机制.当您在C#或Java等语言中使用类时,这可能是最重要的事情.

http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)

继承允许您重用代码,添加新字段,属性和方法或替换先前定义的类的方法和属性.

虚拟和覆盖允许您替换方法的内容,当我说替换时,我说替换.

我会建议你一个很好的例子.

public class MyClassEnglish
{
    public virtual string SomethingToSay()
    {
        return "Hello!";
    }

    public void WriteToConsole()
    {
        Console.WriteLine(this.SomethingToSay());
    }
}

public class MyClassItalian :
    MyClassEnglish
{
    public override string SomethingToSay()
    {
        return "Ciao!";
    }
}

int main()
{
    MyClassItalian it = new MyClassItalian();

    it.WriteToConsole();
}
Run Code Online (Sandbox Code Playgroud)

如果省略virtual和override,MyClassItalian将打印出"Hello!" 而不是"Ciao!".

在您的示例中,您将显示阴影技术,但编译器应该给出警告.如果要隐藏基类中的方法,则应添加"new"关键字.隐藏方法并不是最重要的!只是藏身.

我想到的一个可能用途是,例如,当您需要某种优化时,可以使用它.

public abstract class MySpecialListBase
{
    public int Count()
    {
        return this.GetCount();
    }

    protected abstract int GetCount();
}

public sealed class MySpecialArrayList : MySpecialListBase
{
    int count;

    public new int Count()
    {
        return this.count;
    }

    protected override int GetCount()
    {
        return this.count;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在......您可以在所有代码中使用MySpecialListBase,当您调用Count()时,它将调用虚方法GetCount().但是如果你只使用MySpecialArrayList,它将调用非虚拟的优化Count()并返回一个字段,从而提高性能.

// This works with all kind of lists, but since it is a more general purpose method it will call the virtual method.    
public void MyMethod(MySpecialListBase list)
{
    Console.WriteLine(list.Count());
}

// This works only with MySpecialArrayList, and will use the optimized method.
public void MyMethod(MySpecialArrayList list)
{
    Console.WriteLine(list.Count());
}
Run Code Online (Sandbox Code Playgroud)