我有这个简单的克隆界面,我想使用它。它看起来应该编译,但事实并非如此。我收到一条消息,说我的BObject
课程没有实现DeepClone()
。我不理解这一点,因为我有DeepClone()
方法而我的BObject
类实现了 IObject
。
interface IDeepCloneable<T>
{
T DeepClone();
}
interface IObject : IDeepCloneable<IObject>
{
string Name { get; }
double Sales { get; }
}
//'BObject' does not implement interface member
// 'IDeepCloneable<IObject>.DeepClone()'
class BObject : IObject
{
public string Name { get; set; }
public double Sales { get; set; }
public BObject DeepClone()
{
return new BObject() { Name = this.Name, Sales = this.Sales };
}
}
我声明我的界面错了吗?
或者DeepClone
实施?我可以使用这段代码:
public IObject DeepClone() //returns an IObject instead of a BObject
{
return new BObject() { Name = this.Name, Sales = this.Sales };
}
我遇到的问题是没有检查BObject.DeepClone()
方法返回BObject
的结果。我可以有一个看起来像这样的课:
class BObjectImposter : IObject
{
public string Name { get; set; }
public double Sales { get; set; }
public IObject DeepClone()
{
//returns a BObject instead of a BObjectImposter
return new BObject() { Name = this.Name, Sales = this.Sales };
}
}
使用这个课,我可以这样写:
BObjectImposter objImp = new BObjectImposter();
IObject copy = objImp.DeepClone();
我可能希望copy
是BObjectImposter
的实现,但它实际上是一个不相关的类BObject
的实现,它恰好也实现了IObject
。我理解接口的意义在于我使用哪种实现并不重要,但这对我来说似乎不是好的代码。也许在BObjectImposter
实现的某个地方,我希望DeepClone()
返回一个BObjectImposter
对象。此外,IObject的一个实现不应该依赖于IObject的另一个实现。
也许我可以使IObject
成为一个抽象类并在那里声明DeepClone()
。如果我有一个实现(称之为ObjectA
),我需要在构造函数中设置Name
之前设置Sales
,以及另一个实现(调用它{{}},这似乎可能会破坏我的设计{1}})我需要在构造函数中设置ObjectB
之前设置Sales
。
答案 0 :(得分:5)
正如您在问题中暗示的那样,IObject
实现了IDeepClonable&lt; IObject &gt;,因此其DeepClone()
方法必须返回IObject
。
您需要一直使用CRTP:
interface IObject<T> : IDeepCloneable<T> where T : IObject<T>
class BObject : IObject<BObject>
(您还应该将where T : IDeepCloneable<T>
添加到IDeepCloneable
)
答案 1 :(得分:1)
因为IObject继承IDeepCloneable<IObject>
所以DeepClone
将返回IObject
。以下应该有效:
interface IDeepCloneable<T>
{
T DeepClone();
}
interface IObject<T> : IDeepCloneable<T>
{
string Name { get; }
double Sales { get; }
}
//'BObject' does not implement interface member
// 'IDeepCloneable<IObject>.DeepClone()'
class BObject : IObject<BObject>
{
public string Name { get; set; }
public double Sales { get; set; }
public BObject DeepClone()
{
return new BObject() { Name = this.Name, Sales = this.Sales };
}
}