簡體   English   中英

C# 更改子類中抽象屬性的返回類型

[英]C# Changing Return Type of Abstract Property in Child Class

TLDR:無論如何要覆蓋抽象屬性並同時更改它的返回類型,就像您可以使用具體屬性一樣? 我知道直接的答案是“不”,但我想知道是否有任何不涉及添加第二個屬性的解決方法。

假設我有這個抽象類:

public abstract class Item {
  public abstract string SerialNumber { get; }
  public string PartNumber => "34";
}

假設我想要一個實現ItemToy類。 假設出於某種原因,我希望SerialNumberPartNumber屬性在子類中都是 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.

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