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

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

例1:

class BaseClass { public virtual string call() { return "A"; } } class DerivedClass : BaseClass { public override string call() { return "B"; } } 

输出:B

例2:

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

输出仍然是相同的:

输出:B

运行测试:

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

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

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

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

现在做:

 BaseClass obj = new DerivedClass(); Console.WriteLine(obj.call()); 

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

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

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

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

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

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

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

如果省略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; } } 

现在……您可以在所有代码中使用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()); } 

最好的例子我可以想到它在哪里有用的是当你创建自己的对象(类)时,你必须将该对象的列表添加到combobox中。

将对象添加到combobox时,您希望能够控制每个项目显示的文本。 Object.toString是一个虚方法。 http://msdn.microsoft.com/en-us/library/system.object.tostring.aspx因此您可以覆盖该方法并设置.toString以通过覆盖它来显示有关对象的正确信息。

 public MyClass() { private int ID; public override string ToString() { return "My Item:" + ID; } } 

方法覆盖:

在父类中定义或实现虚方法然后在后代类中替换它的位置。

当您决定将方法声明为虚拟时,您将授予派生类以使用自己的实现扩展和覆盖该方法。 您也可以让扩展方法调用父方法的代码。

在大多数OO语言中,您还可以选择隐藏父方法。 当您使用相同的签名引入同一命名方法的新实现而不覆盖时,您将隐藏父方法。

C#重写在C#中,您在父类中使用virtual关键字指定虚方法,并使用override关键字在子类中扩展(或替换)它。

在descendant方法中使用base关键字来执行父方法中的代码,即base.SomeMethod()。

语法示例:

 class Robot { public virtual void Speak() { } } class Cyborg:Robot { public override void Speak() { } } 

覆盖详细信息您不能覆盖常规的非虚方法,也不能覆盖静态方法。 父方法的第一个版本必须是虚拟或抽象的。 您可以覆盖标记为virtual,abstract或override(已经被覆盖)的任何父方法。 方法必须具有相同的签名。 这些方法必须具有相同的可见性(相同的访问级别)。 使用base关键字引用父类,如base.SomeMethod()中所示。 C#覆盖示例以下代码片段演示如何使用virtual和override覆盖后代类中的父方法。

 using System; class Dog { public virtual void Bark() { Console.WriteLine("RUFF!"); } } class GermanShepard:Dog { public override void Bark() { Console.WriteLine("Rrrrooouuff!!"); } } class Chiuaua:Dog { public override void Bark() { Console.WriteLine("ruff"); } } class InclusionExample { public static void Main() { Dog MyDog=new Dog(); MyDog=new GermanShepard(); MyDog.Bark(); // prints Rrrrooouuff!! MyDog=new Chiuaua(); MyDog.Bark(); // prints ruff; } } 

使用New隐藏方法使用new关键字引入父方法的新实现(这会隐藏父方法)。 您可以在不使用new的情况下隐藏方法,但会收到编译器警告。 使用new将禁止警告。

new和override修饰符具有不同的含义。 new修饰符创建具有相同名称,签名和可见性的新成员,并隐藏原始成员。 override修饰符扩展了inheritance成员的实现,并允许您实现基于inheritance的多态。

避免引入新成员:有时有明确的理由引入具有相同名称,签名和父方法可见性的新方法。 在这些明显的案例中,引入新成员是一个强大的function。 但是,如果您没有明确的理由,那么通过将新方法命名为独特且适当的方法,避免引入新版本的方法。

 class Robot : System.Object { public void Speak() { MessageBox.Show("Robot says hi"); } } class Cyborg : Robot { new public void Speak() { MessageBox.Show("hi"); } } 

调用基类版本常见任务在OO中,首先执行父方法代码然后添加代码来扩展方法。 使用base关键字引用父类,如base.SomeMethod()中所示。

 class Robot : System.Object { public virtual void Speak() { MessageBox.Show("Robot says hi"); } } class Cyborg : Robot { public override void Speak() { base.Speak(); MessageBox.Show("hi"); } }