[英]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.