33

我有四节课。请求、派生请求、处理程序、派生处理程序。Handler 类有一个带有以下声明的属性:

public abstract Request request { get; set; }

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

public override DerivedRequest request { get; set; }

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

4

6 回答 6

21

这并不是一个很好的结构化事物的方法。执行以下操作之一

1)只是不要更改返回类型,并在子类中正常覆盖它。在你可以返回一个使用基类签名的DerivedHandler实例。任何使用它的客户端代码都可以根据需要选择将其转换为。DerivedRequestRequestDerivedRequest

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>()
于 2011-06-14T22:58:45.990 回答
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>
{
}
于 2011-06-14T22:55:42.923 回答
5

除了隐藏原始属性:

public new DerivedRequest Request { get;set;}

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

通常,如果您考虑使用new关键字,那么您就走错了路。在某些情况下,它是必要的和必需的,但是,在大多数情况下,它不是。

相反,创建另一个属性:

public DerivedRequest DerivedRequest {/* make adequate conversions here*/ }

这样,您就可以清楚地了解 OOP,并以清晰的方式获取信息。

于 2011-06-14T22:47:07.797 回答
1

编辑:您不能更改派生类型的类型,但new可能会有所帮助:

在派生类型中...

public new DerivedRequest request
{
   get{return (DerivedRequest) base.request;}
   set{base.request = value;}
}
public override Request request
{
   get{return base.request;}
   set{base.request = (DerivedRequest) value;} // Throws InvalidCastException if misused.
}
于 2011-06-14T22:44:23.917 回答
0

这在理论上是不可能的。覆盖对于返回类型必须是协变的(即返回类型必须更具体或相同),而对于参数必须是逆变的(即参数类型必须不太具体或相同)。因此,您的新类型必须同时有效地协变和逆变Request- 这意味着,唯一可能的类型是 just Request

因此,在 C# 中不允许更改覆盖的属性类型。

于 2011-06-14T22:48:50.177 回答
0
public class Request{}

public class DerivedRequest : Request{}

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

public class DerivedHandler : Handler<DerivedRequest>
{
  public override DerivedRequest Request { get; set; }
}
于 2011-06-14T22:59:31.007 回答