在 C# 中使用派生返回类型覆盖抽象属性
我有四节课。请求、派生请求、处理程序、派生处理程序。 Handler 类有一个带有以下声明的属性:
public abstract Request request { get; set; }
DerivedHandler 需要重写此属性,以便它返回 DerivedRequest:
public override DerivedRequest request { get; set; }
有人知道如何实现此功能吗?
I have four classes. Request, DerivedRequest, Handler, DerivedHandler. The Handler class has a property with the following declaration:
public abstract Request request { get; set; }
The DerivedHandler needs to override this property so that it returns DerivedRequest instead:
public override DerivedRequest request { get; set; }
Does anyone have any ideas about how to make this work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这实际上并不是一个构建事物的好方法。执行以下操作之一
1) 只是不要更改返回类型,并在子类中正常覆盖它。在
DerivedHandler
中,您可以使用Request
的基类签名返回DerivedRequest
的实例。如果愿意,任何使用此方法的客户端代码都可以选择将其转换为DerivedRequest
。2) 如果泛型不应该是多态的,请改用泛型。
This isn't really a good way to structure things. Do one of the following
1) Just don't change the return type, and override it normally in the subclass. In
DerivedHandler
you can return an instance ofDerivedRequest
using the base class signature ofRequest
. Any client code using this can choose to cast it toDerivedRequest
if they want to.2) Use generics instead if they are not supposed to be polymorphic.
在 C# 语言中,您不允许更改继承方法的签名,除非您将其替换为具有相同名称的另一个方法。该技术称为“成员隐藏”或“遮蔽”。
如果您使用的是 .NET 2.0 或更高版本,可以通过将
Request
属性的返回类型转换为Handler
类的泛型类型参数来解决此问题。然后,DerivedHandler
类会将DerivedRequest
类指定为该类型参数的参数。这是一个例子:
In the C# language you are not allowed to change the signature of an inherited method, unless you substitute it with another method with the same name. This technique is referred to as "member hiding" or "shadowing".
If you are using .NET 2.0 or later, you could solve this problem by turning the return type of the
Request
property into a generic type parameter of theHandler
class. TheDerivedHandler
class would then specify theDerivedRequest
class as argument for that type parameter.Here's an example:
除了隐藏原始财产之外:
但是,我强烈建议不要这样做。隐藏一些应该被覆盖的东西会带来麻烦,特别是如果该属性不是简单的自动生成的属性。另外,如果将其用作接口或基类,则为原始实现(在这种情况下,为继承树中较高的一个类)。如果您正在实现抽象类或接口,您甚至无法隐藏原始签名,因为您需要实现它。
通常,如果您考虑使用
new
关键字,那么您就走错了路。在某些情况下,这是必要和必需的,但在大多数情况下,并非如此。相反,创建另一个属性:
这样,您就可以清楚地了解 OOP,并以清晰的方式获取信息。
Except for hiding the original property:
However, I strongly advise against that. Hiding something supposed to be overriden is inviting trouble, especially if the property isn't a simple auto generated one. Also, if using it as an interface or base class, the original implementation (in that case, one class higher in the inheritance tree). If you are implementing an abstract class or interface, you won't even be able to hide the original signature, as you are required to implement it.
Usually, if you think about using the
new
keyword, you are on the wrong track. There are cases where it is necessary and required, however, in most cases, it isn't.Instead, make another property:
That way, you are on the clear side concerning OOP and you get your information in a clear way.
编辑:
您无法更改派生类型的类型,但
new
可能会有所帮助:在派生类型中...
Edit:
You can't change the type on a derived type, but
new
might help:In the derived type...
这在理论上是不可能的。覆盖对于返回类型必须是协变的(即,返回类型必须更具体或相同),对于参数来说必须是逆变的(即参数类型必须是不太具体或相同)。因此,您的新类型必须同时有效地针对
Request
进行协变和逆变——这意味着,唯一可能的类型就是Request
。因此,C# 中不允许更改重写的属性类型。
This is not theoretically possible. The override must be covariant for return type (that is, the return type must be more specific or the same), and contravariant for parameter (that is, parameter type must be less specific or the same). So your new type must be effectively at the same time covariant and contravariant with respect to the
Request
-- that means, the only possible type is justRequest
.For this reason, it's not allowed in C# to change the type of properties for overrides.