C#中new和override的区别

本文详细解析了C#中override与new关键字的区别及应用。通过实例演示了如何使用override来实现多态,以及new如何隐藏基类方法。同时介绍了在不同上下文中调用这些方法的行为变化。

在C#中,override和new都会覆盖父类中的方法。那它们两者之前有什么区别呢?

  • override是指“覆盖”,是指子类覆盖了父类的方法。子类的对象无法再访问父类中的该方法。
  • new是指“隐藏”,是指子类隐藏了父类的方法,当然,通过一定的转换,可以在子类的对象中访问父类的方法。

以下代码的运行结果是什么?

class Base
{
	public virtual void F1()
	{
		Console.WriteLine("Base's virtual function F1");
	}
	public virtual void F2()
	{
		Console.WriteLine("Base's virtual fucntion F2");
	}
}
class Derived:Base
{
	public override void F1()
	{
		Console.WriteLine("Derived's override function F1");
	}
	public new void F2()
	{
		Console.WriteLine("Derived's new function F2");
	}
}
class Program
{
	public static void Main(string[] args)
	{
		Base b1 = new Derived();
		//由于子类覆盖了父类的方法,因此这里调用的是子类的F1方法。也是OO中多态的体现
		b1.F1();
		//由于在子类中用new隐藏了父类的方法,因此这里是调用了隐藏的父类方法
		b1.F2();   
	}
}
或者我们用以下的代码更加容易明白:  
class Program  
{   
	public static void Main(string[] args)   
	{    
		Derived b1 = new Derived();    
		//由于子类覆盖了父类的方法,因此这里调用的是子类的F1方法。也是OO中多态的体现    
		((Base) b1).F1();
		//由于在子类中用new隐藏了父类的方法,因此这里是调用了隐藏的父类方法    
		((Base) b1).F2();
	} 
}

以上两个的输出都为:

Derived's override function F1

Base's virtual fucntion F2  

在上面的例子中,由于F1覆盖(override)了原先的方法,因此即使转成父类的对象,仍旧调用了子类的F1方法。而由于子类的F2方法只是“隐藏”了父类的F2方法,因此当强制转换成父类(Base)的对象去调用F2方法时,调用了原先隐藏的父类的F2方法。

 

### C# `new` 和 `override` 的区别及使用场景 在 C# 面向对象编程,`new` 和 `override` 是两个重要的关键字,它们分别用于不同的上下文来处理继承和多态性。以下是两者的定义、行为差异以及实际应用场景的详细介绍。 --- #### 1. **`override` 关键字** `override` 用于扩展或修改基类的虚方法(virtual method),从而实现运行时多态性。这意味着当通过基类引用调用被标记为 `override` 的方法时,会执行派生类的具体实现而非基类的默认实现。 ##### 特点 - 基类的方法必须声明为 `virtual` 或者 `abstract` 才能被重写。 - 使用 `override` 不仅改变了方法的行为,还参与了动态绑定机制,即运行时决定调用哪个方法。 - 如果试图重写一个未标记为 `virtual` 的方法,则编译器会报错。 ##### 示例代码 ```csharp class Animal { public virtual void Say() { Console.WriteLine("Animal says something."); } } class Dog : Animal { public override void Say() { Console.WriteLine("Dog barks!"); } } class Program { static void Main(string[] args) { Animal animal = new Dog(); // 多态性:animal 引用指向 Dog 对象 animal.Say(); // 输出 "Dog barks!",因为 Say 方法被重写了 } } ``` --- #### 2. **`new` 关键字** `new` 用于隐藏基类的同名成员(无论是方法还是属性)。这实际上是一种名称遮蔽(name hiding)行为,而不是真正的重写。即使通过基类类型的变量调用了该方法,仍会执行基类的原始实现。 ##### 特点 - 使用 `new` 不会影响基类的行为,也不会触发多态性。 - 当通过派生类实例调用时,会执行派生类的新实现;但如果通过基类引用调用,则依然执行基类的旧实现。 - 编译器通常会对这种隐式的覆盖发出警告,建议显式标注 `new` 来表明意图。 ##### 示例代码 ```csharp class Animal { public void Say() { Console.WriteLine("Animal says something."); } } class Cat : Animal { public new void Say() // 使用 new 显式标明这是新定义的方法 { Console.WriteLine("Cat meows!"); } } class Program { static void Main(string[] args) { Animal animal = new Cat(); // 动物引用指向猫的对象 animal.Say(); // 输出 "Animal says something.",因为没有发生重写 Cat cat = new Cat(); // 猫引用指向猫的对象 cat.Say(); // 输出 "Cat meows!" } } ``` --- #### 3. **主要区别总结** | 属性 | `override` | `new` | |--------------------|--------------------------------------------|-------------------------------------------| | 是否改变原有行为 | 修改并替换基类方法 | 隐藏而不更改基类方法 | | 是否支持多态 | 支持 | 不支持 | | 基类方法的要求 | 必须是 `virtual` 或 `abstract` | 没有特殊要求 | | 调用方式的影响 | 依赖于运行时的实际类型 | 严格遵循静态类型 | --- #### 4. **典型使用场景** - **`override` 的适用场景** - 当希望子类能够提供特定的功能实现,并且需要利用面向对象的多态特性时。 - 在设计框架或者库时,允许使用者自定义某些核心逻辑。 - **`new` 的适用场景** - 子类确实不需要保留父类原有的语义,而是完全重新定义了一个独立的操作。 - 需要避免意外地干扰现有系统的正常工作流。 --- ### 总结 为了编写清晰、可维护性强的应用程序,在选择 `override` 或 `new` 之前应仔细权衡其用途与后果[^1]。一般而言,优先采用 `override` 实现更灵活的设计模式,除非明确知道为何要用 `new` 替代已有功能[^2][^3]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值