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