簡體   English   中英

用 c# 中的派生返回類型覆蓋抽象屬性

[英]Overriding an abstract property with a derived return type in c#

我有四節課。 請求、派生請求、處理程序、派生處理程序。 處理程序 class 具有具有以下聲明的屬性:

public abstract Request request { get; set; }

DerivedHandler 需要覆蓋此屬性,以便它返回 DerivedRequest:

public override DerivedRequest request { get; set; }

有人對如何使這項工作有任何想法嗎?

這並不是一個很好的結構化事物的方法。 執行以下操作之一

1)只是不要更改返回類型,並在子類中正常覆蓋它。 DerivedHandler ,您可以使用Request的基本 class 簽名返回DerivedRequest的實例。 如果需要,任何使用它的客戶端代碼都可以選擇將其轉換為DerivedRequest

2)如果它們不應該是多態的,則使用 generics 代替。

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

public class Handler: HandlerBase<Request>()

public class DerivedHandler: HandlerBase<DerivedRequest>()

在 C# 語言中,您不得更改繼承方法的簽名,除非您將其替換為具有相同名稱的其他方法 這種技術被稱為“成員隱藏”或“隱藏”。

如果您使用的是 .NET 2.0 或更高版本,則可以通過將Request屬性的返回類型轉換為Handler class 的泛型類型參數來解決此問題。 然后, DerivedHandler class 將指定DerivedRequest class 作為該類型參數的參數。

這是一個例子:

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

// DerivedHandler.cs
public class DerivedHandler : Handler<DerivedRequest>
{
}

除了隱藏原始屬性:

public new DerivedRequest Request { get;set;}

但是,我強烈建議不要這樣做。 隱藏應該被覆蓋的東西會招來麻煩,特別是如果該屬性不是簡單的自動生成的。 此外,如果將其用作接口或基礎 class,則為原始實現(在這種情況下,inheritance 樹中的 class 更高)。 如果您正在實現抽象 class 或接口,您甚至無法隱藏原始簽名,因為您需要實現它。

通常,如果您考慮使用new關鍵字,那么您就走錯了路。 在某些情況下,它是必要的和必需的,但是,在大多數情況下,它不是。

相反,創建另一個屬性:

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

這樣,您就可以清楚地了解 OOP 並以清晰的方式獲取信息。

編輯:您不能更改派生類型的類型,但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.
}

這在理論上是不可能的。 覆蓋對於返回類型必須是協變的(即返回類型必須更具體或相同),而對於參數必須是逆變的(即參數類型必須不太具體或相同)。 因此,您的新類型必須同時有效地與Request協變和逆變——這意味着,唯一可能的類型就是Request

因此,C# 中不允許更改覆蓋的屬性類型。

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; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM