繁体   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