C# 设计:为什么抽象方法需要 new/override 而虚拟方法不需要?
为什么抽象方法需要 new/override 而虚拟方法不需要?
示例1:
abstract class ShapesClass
{
abstract public int Area(); // abstract!
}
class Square : ShapesClass
{
int x, y;
public int Area() // Error: missing 'override' or 'new'
{
return x * y;
}
}
编译器将显示此错误: 要使当前成员覆盖该实现,请添加 override 关键字。否则添加 new 关键字
示例 2:
class ShapesClass
{
virtual public int Area() { return 0; } // it is virtual now!
}
class Square : ShapesClass
{
int x, y;
public int Area() // no explicit 'override' or 'new' required
{
return x * y;
}
}
通过默认隐藏该方法,这将可以正常编译。
我完全理解技术差异。但我想知道为什么这种语言是这样设计的。在“示例 2”中也有相同的限制不是更好吗?我的意思是,在大多数情况下,如果您创建一个与父类中同名的方法,您通常会打算覆盖它。因此,我认为明确声明 Override/New 对虚拟方法也有意义。
这种行为有设计方面的原因吗?
更新: 第二个示例实际上会引起警告。第一个示例显示错误,因为子类需要实现抽象方法。我没有看到 VS 中的警告..现在对我来说完全有意义。谢谢。
Why is new/override required on abstract methods but not on virtual methods?
Sample 1:
abstract class ShapesClass
{
abstract public int Area(); // abstract!
}
class Square : ShapesClass
{
int x, y;
public int Area() // Error: missing 'override' or 'new'
{
return x * y;
}
}
The compiler will show this error:
To make the current member override that implementation, add the override keyword. Otherwise add the new keyword
Sample 2:
class ShapesClass
{
virtual public int Area() { return 0; } // it is virtual now!
}
class Square : ShapesClass
{
int x, y;
public int Area() // no explicit 'override' or 'new' required
{
return x * y;
}
}
This will compile fine, by hiding the method by default.
I fully understand the technical differences. However I wonder why the language was designed that way. Wouldn't it be better to have the same restriction in "Sample 2" as well? I mean in most cases if you create a method with the same name as in the parent class, you usually intent to override it. So I think explicitly stating Override/New would make sense on virtual methods as well.
Is there a design-wise reason for this behavior?
Update:
The 2nd sample actually causes a warning. The first sample shows an error because the subclass is required to implement the abstract method. I didn't see the warning in VS.. makes perfectly sense to me now. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用 .NET 3.5 SP1 中附带的 C# 3.0 编译器或 .NET 4.0 中附带的 C# 4.0 编译器,我在第一个示例中收到以下错误:
对于第二个,以下警告:
在第一种情况下,这是一个错误,因为您实际上并未重写基本方法,这意味着具体类中没有抽象方法的实现。在第二种情况下,这是一个警告,因为代码在技术上是正确的,但编译器怀疑这不是您的意思。这就是启用“将警告视为错误”编译设置通常是个好主意的原因之一。
所以我无法重现你的行为,并且编译器的行为对我来说看起来是正确的。您使用哪个版本的编译器?
Using either the C# 3.0 compiler as shipped in .NET 3.5 SP1, or the C# 4.0 compiler as shipped in .NET 4.0, I get the following error for your first example:
And the following warning for the second one:
In the first case it's an error because you aren't actually overriding the base method, which means there is no implementation for the abstract method in a concrete class. In the second case it's a warning because the code is technically correct, but the compiler suspects that it isn't what you meant. This is one of the reasons it's generally a good idea to enable the "treat warnings as errors" compilation setting.
So I can't repro your behaviour, and the behaviour of the compiler looks right to me. Which version of the compiler are you using?
这是直接来自 C# 规范的答案。
Here's the answer straight from the C# spec.
不同之处在于抽象方法必须被重写,而虚拟方法则不需要。
继承抽象类(在非抽象类中)而不实现所有抽象成员是错误的,但只有在从类继承而不指定
override
或new
时才会收到警告code> 为虚方法。The difference is that the abstract method has to be overridden, but the virtual doesn't.
It's an error to inherit the abstract class (in a non-abstract class) without implementing all abstract members, but you only get a warning when inheriting from the class without specifying
override
ornew
for the virtual method.版本控制
乍一看,您可能会认为方法隐藏似乎不是特别有用。有一种情况
但是,您可能需要使用它的地方。假设您想使用一个名为
MotorVehicle
的类是由另一个程序员编写的,并且您想使用此类来派生您自己的类。更远,
我们还假设您想在派生类中定义一个 Accelerate() 方法。例如:
接下来,假设另一个程序员后来修改了 MotorVehicle 类并决定
添加她自己的
virtual Accelerate()
方法:其他程序员添加此
Accelerate()
方法会导致问题:Car
类中的Accelerate()
方法隐藏了现在定义的继承的Accelerate()
方法他们的
MotorVehicle
类。稍后,当您编译Car
类时,编译器并不清楚您是否确实希望您的方法隐藏继承的方法。正因为如此,
当您尝试编译 Car 类时,编译器会报告以下警告:
Versioning
At first glance, you may think that method hiding doesn’t appear particularly useful. There is a situation
where you might need to use it, however. Let’s say you want to use a class named
MotorVehicle
thatwas written by another programmer, and you want to use this class to derive your own class. Further,
let’s also assume you want to define an
Accelerate()
method in your derived class. For example:Next, let’s suppose that the other programmer later modifies the MotorVehicle class and decides
to add her own
virtual Accelerate()
method:The addition of this
Accelerate()
method by the other programmer causes a problem: TheAccelerate()
method in yourCar
class hides the inheritedAccelerate()
method now defined intheir
MotorVehicle
class. Later, when you come to compile yourCar
class, it isn’t clear to the compilerwhether you actually intended your method to hide the inherited method. Because of this, the
compiler reports the following warning when you try to compile your Car class:
我认为在第一种方式中你会得到编译器错误,因为抽象方法是隐藏的并且没有实现(所以实际上你的类是错误的,并且很难找出原因)。在第二种情况下,您只会收到警告,因为该类可用。
I think in the first way you get the compiler error, because the abstract method is hidden and not implemented (so effectively your class is wrong, and it would be difficult to figure out why). In the second case you get only a warning, because the class is usable.