c#中new和override的区别. virtual和abstract方法的区别.

本文详细解析了C#中虚函数的概念及应用,包括new关键字的隐藏特性与override关键字的重写特性,对比了二者在不同场景下的行为差异。此外,还介绍了virtual与abstract的区别及其在继承中的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近做程序用到了虚函数:virtual ,所以对实现类中使用new 和 override的区别温习:

new

C#中new关键字表示隐藏,是指加上new关键字的属性或函数将对本类和继承类隐藏基类的同名属性或函数.

public classA

{

        public  virtual  void  Method()

        {

                Console.WriteLine("This Method in Class A!");

        }

}

public  classB:A

{

        public  new  void  Method()

        {

                Console.WriteLine("This Method in Class B!");

        }

}

对于上面这个例子来说,假如运行 A  a = new B(); a.Method(); 会输出  This Method in Class A !, 这是因为 classB 继承calssA,

现在B中的Method函数隐藏A中的Method,所以从B(包括继承于B的子类)的角度来看类中的Method就是B.Method, A的Method

不可见,但是如果从A的角度来看B,A只认识类B中继承于A的Method函数,对于B类中的Method它不可见,所以 A a =new B();

a.Method();相当于是调用了类B中继承于A的Method函数.

 

override

C#中override关键字表示重写,对于加上override关键字的属性或函数将完全覆盖基类的同名虚函数或虚属性,使基类的虚属性和

虚函数在整个继承链中都不可见(在子类中用base关键字调用除外)。

public  class A

{

        public virtual void Method()

        {

              Console.WriteLine("This Method in Class A!");

        }

}

public  class B:A

{

        public override void Method()

        {

              Console.WriteLine("This Method in Class B!");

        }

}

对于上面这个例子来说,假如运行 A a= new B(); a.Method();会输出 This Method in Class B! ,因为ClassB的Method函数完全覆盖

基类的同名虚函数Method,使整个继承链中看见的Method函数都是B中的Method,所以就算是以A角度来看B,A看到的Method函数也是

B中的Method,因为A中的Method完全被B的覆盖了.

但是如果要在B的对象中调用A的Method函数可以使用base关键字,比如

public  class A

{

        public virtual void Method()

        {

              Console.WriteLine("This Method in Class A!");

        }

}

public  class B:A

{

        public override void Method()

        {

             base.Method();

        }

}

 A a = new B(); a.Method(); 会输出 This Method in Class A!.   base.Method();表示调用类B中继承于基类A的Method.

 

new 、override与interface

接口在相互继承的时候也会隐藏基接口的同名属性或函数,但是对于接口来说很特殊,隐藏对于基接口来说是不起作用的,

接口内部的属性或函数都只是声明,它们都指向实现接口的类中的同名实现函数,通过接口调用接口的属性和函数的时候

都会去调用实现类中从上到下最先可见的同名函数和同名属性:

public  interface IA { void Method() ;}

public  interface IB:IA { new void Method(); }

public  class IClass:IB { public void Method(){ Console.writeline("this method in class IClass!");

public  class ISubClass : IClass {public new void Method() { Console.writeline("this method in class ISubClass!");}

IA   ia = new ISubClass();  ia.Method();  输出  this method in class IClass! 因为对于ia来说在继承链中最先见到的同名实现函数

是类IClass的Method函数.

上面的例子稍作修改:

public  interface IA { void Method() ;}

public  interface IB:IA { new void Method(); }

public  class IClass:IB { public virtual  void Method(){ Console.writeline("this method in class IClass!");

public  class ISubClass : IClass {public override void Method() { Console.writeline("this method in class ISubClass!");}

IA   ia = new ISubClass();  ia.Method();  输出  this method in class ISubClass! 因为继承链中的Method函数都被ISubClass的

Method覆盖了,所以对于ia来说在继承链中最先见到的同名实现函数是类 ISubClass的Method函数.

 

virtual 和  abstract

 

abstract可以修饰类和方法。

virtual在C#中用于修饰方法和属性。

 

abstract修饰的类叫做抽象类,抽象类中必须有抽象方法,同时也可以有非抽象方法,既可以有方法的具体实现,继承抽象父类的子类中,如果子类没有

实现抽象父类中的抽象方法,那么这个子类也必须声明为抽象的,即只要类中有抽象的方法那么这个类就一定是抽象类,且抽象类不能实例化,abstract修饰的方法不能实现。

如,

public abstract Light {

public abstract  void  turnon();

public abstract  void  turnoff();

};

在派生类中一定要有抽象方法的具体实现。

注意:抽象方法只能在抽象类中。

 

virtual 修饰的方法可以在一般类中。

其修饰的方法在父类中一定要有实现,即使只是一对大括号。

public  Light {

public  virtual  void  turnon() {};

};

 

抽象方法和virtual方法在派生类中的重载都是使用关键字override.

 

 一、Virtual方法(虚方法)

     virtual 关键字用于在基类中修饰方法。virtual的使用会有两种情况:

     情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。

     情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。

二、Abstract方法(抽象方法)

     abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现。抽象方法的实现必须在派生类中使用override关键字来实现。

 

### C# 中 `virtual` `abstract` 关键字的区别 #### 定义与特性 - **Virtual 方法**:通过 `virtual` 关键字可以修改方法、属性、索引器或事件声明,允许派生对其进行重写。这表示任何继承该成员的都可以提供自己的实现方式[^2]。 ```csharp public class BaseClass { public virtual void DisplayMessage() { Console.WriteLine("Base Class Message"); } } public class DerivedClass : BaseClass { public override void DisplayMessage() { Console.WriteLine("Derived Class Message"); } } ``` - **Abstract 方法**:隐含地是一个虚拟的方法,因此不需要显式地标记为 `virtual` 。此方法仅定义签名而不给出具体实现;它强制要求所有的非抽象子都必须覆盖此方法并提供具体的逻辑[^1][^3]。 ```csharp public abstract class AbstractClass { public abstract void ShowDetails(); } public class ConcreteClass : AbstractClass { public override void ShowDetails() { Console.WriteLine("Concrete Implementation Details"); } } ``` #### 使用场景 对于何时应该选用哪种机制,则取决于设计意图: - 如果希望给定默认行为但仍让后代有机会改变这种行为的话,那么就应当采用 `virtual` 成员。 - 当创建框架或者库的时候,如果某些功能必须要由使用者来完成而不能提前确定其实现细节时,就应该考虑使用 `abstract` 及其成员[^4]。 #### 静态上下文中不可用 值得注意的是,在抽象方法声明中不允许使用静态(`static`)修饰符,因为这些方法本质上就是要被实例化后的对象所调用,并且它们总是会被其子中的相应版本替换掉。同样地,由于已经自动具备了可覆写的性质,故也不应再额外加上 `virtual` 限定词[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值