C# 从具有继承接口的父级实现继承接口
假设我有以下3个接口(格式设计为简洁): 我有二级和三级类,它们继承各自的接口(格式设计是为了简洁): 我希望能够将实现的类实现到实现两个接口的根类中,类似于:C# 从具有继承接口的父级实现继承接口,c#,inheritance,interface,C#,Inheritance,Interface,假设我有以下3个接口(格式设计为简洁): 我有二级和三级类,它们继承各自的接口(格式设计是为了简洁): 我希望能够将实现的类实现到实现两个接口的根类中,类似于: public class Root : IRoot { public Secondary secondary { get; set; } public Tertiary tertiary { get; set; } public string foo { get; set; } // This wouldn't
public class Root : IRoot
{
public Secondary secondary { get; set; }
public Tertiary tertiary { get; set; }
public string foo { get; set; } // This wouldn't need to be cross-compatible
}
public class Root2 : IRoot
{
public Secondary2 secondary { get; set; }
public Tertiary2 tertiary { get; set; }
public double bar { get; set; } // This wouldn't need to be cross-compatible either
}
然后我想做一些类似的事情(对不起,反思不是我的强项):
这样IRoot的所有成员都从根转移到根2
在C#中执行此操作将导致匹配类型错误(CS0738)
换句话说(如果这很难理解的话,我很抱歉)我希望我的根接口使用HAS-A关系中的第二和第三接口的签名,我的IRoot接口将具有这种关系,但是在实现根类时,我也希望实现它们各自的继承类,并且不必使用实际的接口
感谢您抽出宝贵的时间。由于
Root
实现了IRoot
并且IRoot
需要接口类型的属性,您必须在Root
中将这些属性声明为接口
public class Root : IRoot
{
public ISecondary secondary { get; set; }
public ITertiary tertiary { get; set; }
}
这仍然允许您为它们分配类
IRoot root = new Root {
secondary = new Secondary(),
tertiary = new Tertiary()
};
如果出于某种原因,您希望访问不属于IsSecondary
接口的次要
对象的成员,可以这样做:
var secondary = root.secondary as Secondary;
if (secondary != null) {
secondary.DoSomething();
}
另一种方法是使用泛型和泛型类型约束
public interface IRoot<TSecondary, TTeritary>
where TSecondary : ISecondary
where TTeritary : ITertiary
{
public TSecondary secondary
public TTeritary tertiary
}
现在你可以这样做了
var list = new List<IRoot<ISecondary, ITertiary>>();
list.Add(new Root());
list.Add(new Root2());
var list=newlist();
添加(新根());
添加(newroot2());
由于Root
实现了IRoot
并且IRoot
需要接口类型的属性,因此必须在Root
中将这些属性声明为接口
public class Root : IRoot
{
public ISecondary secondary { get; set; }
public ITertiary tertiary { get; set; }
}
这仍然允许您为它们分配类
IRoot root = new Root {
secondary = new Secondary(),
tertiary = new Tertiary()
};
如果出于某种原因,您希望访问不属于IsSecondary
接口的次要
对象的成员,可以这样做:
var secondary = root.secondary as Secondary;
if (secondary != null) {
secondary.DoSomething();
}
另一种方法是使用泛型和泛型类型约束
public interface IRoot<TSecondary, TTeritary>
where TSecondary : ISecondary
where TTeritary : ITertiary
{
public TSecondary secondary
public TTeritary tertiary
}
现在你可以这样做了
var list = new List<IRoot<ISecondary, ITertiary>>();
list.Add(new Root());
list.Add(new Root2());
var list=newlist();
添加(新根());
添加(newroot2());
好的,要实现接口,您必须使用相同的类型,但您可以保留更具体的实现并显式实现接口属性:
public class Root : IRoot
{
public Secondary secondary { get; set; }
public Tertiary tertiary { get; set; }
public string foo { get; set; } // This wouldn't need to be cross-compatible
ISecondary IRoot.secondary {get {return this.secondary;} set{;}}
ITertiary IRoot.tertiary {get {return this.tertiary;} set{;}}
}
这样,您就可以以类型安全的方式使用更多sepcific类型,而无需强制转换。然而,问题在于二级
和三级
的设置器。由于可以传入任何IsSecondary
,因此无法保证传入的对象是次要的
,因此无法安全地将其分配给次要的
属性。你的选择是:
- 强制转换到一个
辅助
,如果它不是该类型,则会引发异常
- 确定是否可以强制转换到辅助,如果不能,则执行其他操作
- 在
get-only中设置属性IRoot
public class Root : IRoot
{
public Secondary secondary { get; set; }
public Tertiary tertiary { get; set; }
public string foo { get; set; } // This wouldn't need to be cross-compatible
ISecondary IRoot.secondary {get {return this.secondary;} set{;}}
ITertiary IRoot.tertiary {get {return this.tertiary;} set{;}}
}
这样,您就可以以类型安全的方式使用更多sepcific类型,而无需强制转换。然而,问题在于二级
和三级
的设置器。由于可以传入任何IsSecondary
,因此无法保证传入的对象是次要的
,因此无法安全地将其分配给次要的
属性。你的选择是:
- 强制转换到一个
辅助
,如果它不是该类型,则会引发异常
- 确定是否可以强制转换到辅助,如果不能,则执行其他操作
- 在
get-only中设置属性IRoot
IRoot的实现是否不止一个?IRoot
的消费者将如何使用它?Yacoub:是的,IRoot将有多个实现。设想两个数据模型是交叉兼容的。一个实现可以是包含部分数据的模板,而另一个具有更多变量的实现可以从中获取信息。很抱歉。我不明白你想做什么。我帮不上忙。你能解释一下为什么要这么做吗?我正在尝试开发一个“接口层次结构”,这样我就可以设计数据模型模板,并轻松地在实现该接口的不同类类型之间移动数据。这有意义吗?IRoot的实现是否不止一个?IRoot
的消费者将如何使用它?Yacoub:是的,IRoot将有多个实现。设想两个数据模型是交叉兼容的。一个实现可以是包含部分数据的模板,而另一个具有更多变量的实现可以从中获取信息。很抱歉。我不明白你想做什么。我没办法。仿制药是天才的杰作。谢谢我将尝试一下,看看它是否与我的程序一起工作。是的!工作得很有魅力!仿制药是一种天才之举。谢谢我将尝试一下,看看它是否与我的程序一起工作。是的!工作得很有魅力@Stanley-对于这种显式接口属性声明的特殊方法,您有什么好的文档吗?我想了解更多。我已经看过了,它演示了成员的显式声明,在本例中是方法。你有关于属性的更详细的资料吗?@D Stanley-你有关于这种特殊解释方法的好文档吗