[英]C# Changing Return Type of Abstract Property in Child Class
TLDR:無論如何要覆蓋抽象屬性並同時更改它的返回類型,就像您可以使用具體屬性一樣? 我知道直接的答案是“不”,但我想知道是否有任何不涉及添加第二個屬性的解決方法。
假設我有這個抽象類:
public abstract class Item {
public abstract string SerialNumber { get; }
public string PartNumber => "34";
}
假設我想要一個實現Item
的Toy
類。 假設出於某種原因,我希望SerialNumber
和PartNumber
屬性在子類中都是 int 值,即使它們是基類中的字符串。 見下文:
public abstract class Toy {
public override int SerialNumber => 5; //Doesn't compile obviously
public new int PartNumber => int.ParseInt(base.PartNumber); //works fine, refines the type but keeps the value
}
我包含PartNumber
只是為了表明我了解new
關鍵字應該如何工作。 那部分對我來說很好用。
我的問題是:有什么方法可以同時覆蓋和優化SerialNumber
的類型? 我知道我上面的內容不起作用,但我正在尋找一個簡單的解決方法。 目標是不使用額外的屬性(如SerialNumberInt
或其他東西),以便Toy
類的方法可以引用SerialNumber
並將其作為 int 獲取。
謝謝!
你試圖做的事情是不可能的。
這樣做的原因是你的基類表達了一個契約,其中一部分是它公開的方法的返回類型。
你的子類不能履行這個契約:假設你有一個類“ItemSubmitter”,它有一個方法“submitItem”,它在內部執行:
string partNumberToSubmit = item.PartNumber;
由於您的示例中的 item.PartNumber 返回一個 int,這將導致異常。 您希望編譯器如何處理這種情況?
所以,這是不可能的。 這個概念被概括為 Barbara Liskov 的 Liskov Substitution Principle,參見例如https://en.wikipedia.org/wiki/Liskov_substitution_principle 。
您可以使用泛型,但這將要求所有基類使用者也是泛型的。 在這種情況下,我會質疑您是否需要一個基類並簡單地使消費者通用。
另請參見C# 用具體屬性覆蓋抽象屬性
看來您前段時間已經回答了您自己的問題(以不同方式表述): https : //stackoverflow.com/a/40657803/11389043
這可以使用泛型來完成。 但在你這樣做之前,你需要確保你正確地解決了你的問題。 也就是說,我使用下面的想法來映射具有公共屬性的域實體,但它們的實體 id 具有不同的Type
。
public abstract class ItemBase<TId>
{
protected ItemBase(TId id)
{
ItemId = id;
}
public TId ItemId { get; }
}
public class Toy : ItemBase<int>
{
public Toy(int id) : base(id)
{
}
}
public class NotAToy : ItemBase<Guid>
{
public NotAToy(Guid id) : base(id)
{
}
}
你可以使用泛型來做到這一點(見下文),或者你可以讓一切都成為一個對象。 然而,這真的不是一個很好的解決方案,但我不知道在這種情況下任意改變類型背后的目的。
public abstract class Item <T,V>
{
public abstract T SerialNumber { get; }
public V PartNumber { get; }
}
public abstract class Toy : Item<int, int>
{
public override int SerialNumber => 5;
public new int PartNumber => int.Parse(base.PartNumber.ToString());
}
public abstract class ToyString : Item<string, string>
{
public override string SerialNumber => "3";
public new string PartNumber => "34";
}
您可以使用泛型來實現這一點,如下所示:
public abstract class Item<T> {
public abstract T SerialNumber { get; }
}
public class Toy : Item<int> {
public override int SerialNumber => 5;
}
但是,您不一定要這樣做。 您可能想確認這種設計是否適合您的情況,因為如果您在派生類上重新定義類型,那么很可能是您定義基類的方式有問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.