在c#中使用派生返回类型覆盖抽象属性

Tre*_*vor 30 c# inheritance overriding derived abstract

我有四节课.Request,DerivedRequest,Handler,DerivedHandler.Handler类具有以下声明的属性:

public abstract Request request { get; set; }
Run Code Online (Sandbox Code Playgroud)

DerivedHandler需要覆盖此属性,以便它返回DerivedRequest:

public override DerivedRequest request { get; set; }
Run Code Online (Sandbox Code Playgroud)

有没有人对如何使这项工作有任何想法?

Jam*_*rgy 18

这不是构建事物的好方法.执行以下操作之一

1)只是不要更改返回类型,并在子类中正常覆盖它.在DerivedHandler您可以返回DerivedRequest使用基类签名的实例Request.使用此任何客户端代码可以选择将其DerivedRequest强制转换为.

2)如果它们不应该是多态的,请使用泛型.

public abstract class HandlerBase<T> where T: Request
{
    public abstract T Request {get;set;}
}

public class Handler: HandlerBase<Request>()

public class DerivedHandler: HandlerBase<DerivedRequest>()
Run Code Online (Sandbox Code Playgroud)


Enr*_*lio 6

在C#语言中,除非用另一个具有相同名称的方法替换它,否则不允许更改继承方法的签名.该技术被称为"成员隐藏"或"阴影".

如果您使用的是.NET 2.0或更高版本,则可以通过将Request属性的返回类型转换为类的泛型类型参数来解决此问题Handler.DerivedHandler然后,DerivedRequest该类将该类指定为该类型参数的参数.

这是一个例子:

// Handler.cs
public class Handler<TRequest> where TRequest : Request
{
    public TRequest Request { get; set; }
}

// DerivedHandler.cs
public class DerivedHandler : Handler<DerivedRequest>
{
}
Run Code Online (Sandbox Code Playgroud)

  • 你当然可以这样做; 只要维持Liskov替换原则,"OOP"中的任何内容都禁止您这样做.例如,在面向对象语言"C++"中,覆盖返回Animal的方法和返回Tiger的方法是合法的.此功能称为"返回类型协方差",在OOP语言中相当常见.它不是C#的一个特性. (3认同)

Fem*_*ref 5

除隐藏原始财产外:

public new DerivedRequest Request { get;set;}
Run Code Online (Sandbox Code Playgroud)

但是,我强烈建议不要这样做.隐藏应该被覆盖的东西会引起麻烦,特别是如果属性不是简单的自动生成属性.此外,如果将它用作接口或基类,则使用原始实现(在这种情况下,继承树中的一个类更高).如果要实现抽象类或接口,则甚至无法隐藏原始签名,因为您需要实现它.

通常,如果您考虑使用new关键字,那么您就走错了路.有些情况下是必要和必要的,但在大多数情况下,情况并非如此.

相反,制作另一个属性:

public DerivedRequest DerivedRequest {/* make adequate conversions here*/ }
Run Code Online (Sandbox Code Playgroud)

这样,你对OOP有明确的了解,你就可以清楚地获得你的信息.