如何实现泛型类的decorator的复制方法



想象一下,您有一个定义泛型值的泛型接口和一个复制构造函数,如下所示(替换ICloneable):

// T: type of value to hold, TU: type of the class itself
interface ICopyable<T,TU> where TU: ICopyable<T,TU> {
T Value { get; set; }
TU Copy();
}

这可以通过如下的布尔值持有者来实现:

class BooleanHolder : ICopyable<Boolean, BooleanHolder> {
public BooleanHolder Copy() { 
return new BooleanHolder(){ Value = Value }; 
}
}

现在的问题是:如何定义一个拥有另一个ICopyable的decorator类?我不起作用的想法是:

class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> {
public DecoratingHolder<T,TU> Copy {
// won't compile as Value is of type T and not of type ICopyable<T,TU> 
// as I expected - why is that?
return new DecoratingHolder<T,TU>(){ Value = Value.Copy };
}
}

注意,我调用Copy也是为了复制类型为ICopyable<T,TU>的值,这是为了确保深度复制。

那么,为了使这个结构发挥作用,我需要改变什么呢?

您可能只需要添加一个约束。您定义了ICopyable<T, TU> where TU : ICopyable<T, TU>,但在DecoratingHolder中,从未在DecoratingHolder上显式约束TU

更具体地说,我认为是这一部分:

class DecoratingHolder<T,TU> : ***ICopyable<ICopyable<T,TU>***

这就是问题的根源。您正在定义ICopyable<T,TU>类型,但TU尚未被约束为ICopyable<T, TU>。(可以从类声明/继承的其余部分中推断出,但编译器没有)添加约束后,编译器就会知道Value是兼容的ICopyable<T,TU>类型。

这对我来说编译得很好(不得不用你提供的伪代码修复一些其他小问题):

class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> 
where TU : ICopyable<T,TU>
{
public ICopyable<T,TU> Value { get; set; }
public DecoratingHolder<T,TU> Copy() {
return new DecoratingHolder<T, TU>(){ Value = Value };
}
}

编辑:回想起来,你甚至需要对ICopyable进行约束吗?似乎并没有做太多的工作,因为您已经一般性地定义了传出类型。除非您在其他地方有代码依赖于它出于某种原因返回ICopyable<T, TU>这一事实(它无论如何都会返回强类型的TUBooleanHolderDecoratingHolder),否则请考虑转储它

interface ICopyable<T,TU>
{
T Value { get; set; }
TU Copy();
}
class BooleanHolder : ICopyable<Boolean, BooleanHolder> 
{
public bool Value { get; set; }
public BooleanHolder Copy() { 
return new BooleanHolder(){ Value = Value }; 
}
}
class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> 
{
public ICopyable<T,TU> Value { get; set; }
public DecoratingHolder<T,TU> Copy() {
return new DecoratingHolder<T, TU>(){ Value = Value };
}
}

编辑:根据您需要深度复制的评论,保留约束(您需要它们),并在Value上调用Copy(对不起,我一定错过了那个细节)

class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> 
where TU : ICopyable<T,TU>
{
public ICopyable<T,TU> Value { get; set; }
public DecoratingHolder<T,TU> Copy() {
return new DecoratingHolder<T, TU>(){ Value = Value.Copy() };
}
}

然后,任何给定类的Copy方法都应该确保它们执行深度复制。(我建议将Copy重命名为DeepCopy,如果您的框架需要进行深度复制,并且您不希望实现意外地进行浅层复制)

一个演员阵容为我工作:

public DecoratingHolder<T, TU> Copy()
{
return new DecoratingHolder<T, TU>() { Value = (ICopyable<T, TU>)Value.Copy() };
}

我想在这种情况下,编译器并没有确定TUICopyable<T, TU>是一样的。

最新更新