我有一个接口(IFoo)和另一个包含List<IFoo>
的接口(IBar),我的目标是实现IFoo(FooImp)并将其用于IBar(BarImp)的实现中。我知道接口不会传递属性,并且您应该使用抽象基类,但是我无法弄清楚如何实现此目的。这是我无法使用的接口和实现,但是我以此为起点:
public interface IFoo
{
bool BoolOne { get; set; }
}
public interface IBar
{
List<IFoo> FooList { get; }
}
/// <summary> Implements IFoo interface </summary>
public class FooImp : IFoo
{
public bool BoolOne { get; set; } //required interface implementation
public bool BoolTwo { get; set; } //new property
}
/// <summary>Implements IBar interface </summary>
public class BarImp : IBar //Error - does not implement
{
public List<FooImp> FooList { get; private set; } //Error: "Does not match the expected type 'IFoo'". No suprise here
}
接下来,我将接口转换为抽象库(FooBase和BarBase)并扩展了它们(FooExt和BarExt):
public abstract class FooBase
{
public abstract bool BoolOne { get; set; }
}
public abstract class BarBase
{
public abstract List<FooBase> FooList { get; protected set; }
}
public class FooExt : FooBase
{
public override bool BoolOne { get; set; } //implement abstract property
public bool BoolTwo { get; set; } //add new property
}
public class BarExt : BarBase //Error: FooList<FooBase> not implemented
{
public override List<FooExt> FooList { get; protected set; } //Error: "Type must be FooBase"
}
我不明白为什么最后一行"Type must be FooBase"
上有错误。我以为FooExt是一个多态的FooBase。
我尝试了Linq ConvertAll()
,overrride
,new
的很多(在此处列出所有内容)组合,并通过构造函数和其他函数传递值,但找不到任何会编译。我应该使用其他设计模式吗?
这不是this的副本,因为我的列表容器是一个接口。这些答案是有帮助的,但对于这个问题是非常正确的。
答案 0 :(得分:1)
通过覆盖,您无法更改成员签名。
假设您的程序用户获得了BarBase
的实例,例如从服务器或任何东西。
class MyServer
{
public BarBase GetBar() { ... }
}
var bar = server.GetBar();
该用户应该如何知道此实例FooList
-属性实际上包含FooExt
的实例?不能这样,因为BarBase
提供的 contract 仅声明了List<FooBase>
。
如果我们能够做到这一点,我们还可以将AnotherFoo
的实例添加到该列表中,该实例也继承自FooBase
:
bar.FooList.Add(new AnotherBar())
现在您的FooList
将包含FooExt
-和AnotherBar
实例。
因此,覆盖时,您必须使用与覆盖成员完全相同的签名。
答案 1 :(得分:1)
在覆盖的方法中,您更改了type参数。您不能这样做,因为它会使签名不同。
您可以做的是使用泛型:
public abstract class Base<T> where T : FooBase
{
public abstract List<T> FooList { get; protected set; }
}
然后您可以像这样覆盖它:
public class Ext : Base<FooExt>
{
public override List<FooExt> FooList { get; protected set; }
}