我想就以下问题提出一些建议: 假设你想为VCL控件编写适配器。所有适配器应具有相同的基类,但在包装特殊控件方面有所不同(例如,从TEdit获取值与从TSpinEdit获取值不同)。 所以第一个想法是创建一个类层次结构,如
TAdapter = class
end;
TEditAdapter = class (TAdapter)
end;
TSpinEditAdapter = class (TAdapter)
end;
现在我想引入一个字段来保存对vcl控件的引用。在我的特殊适配器中,我想 - 当然 - 使用具体的子类。但是Base类还应该包含一个引用(例如,如果我想使用适配器使控件可见)。
可能性1(属性访问者中的向下倾斜):
TAdapter = class
protected
FCtrl : TControl;
end;
TEditAdapter = class (TAdapter)
public
property Control : TEdit read GetControl write Setcontrol;
end;
{...}
function TEditAdapter.GetControl : TEdit;
begin
Result := FCtrl as TEdit;
end;
因此,如果我实现一个特定的方法,我使用属性Control,如果我在我的基类中执行某些操作,我会使用受保护的字段。
可能性2(使用通用基类):
TAdapter = class
end;
TAdapter <T : TControl> = class (TAdapter)
protected
FCtrl : T;
end;
TEditAdapter = class (TAdapter <TEdit>)
end;
您更喜欢哪种解决方案?还是有第三种解决方案,哪种情况更好?
亲切的问候,
基督教
答案 0 :(得分:4)
您无法使用泛型来解决此问题,因为您将处于以下两种情况之一:
Text
属性)在祖先类中定义。在这种情况下,您不需要泛型,因为您可以使用一个适配器作为祖先并解决所有后代的问题。Text
TMyClass
属性的适配器。我们假设TMyClass
是引入Text
属性的那个。为了访问它,您需要将泛型类型声明为TGeneric<T:TMyClass>
,而这实际上并不是通用的。在我看来,最好的办法是为每个班级编写特定的适配器,如第一个选项。您可以使用RTTI技巧使您的第一个选项更容易实现,但我不确定它是否值得。
答案 1 :(得分:0)
泛型版本可以避免一些重复的代码,至少在TAdapter类中是这样。通过使用T
类型,它将允许大量共享代码。
另一方面,由于VCL层次结构,大多数使用的属性和方法已经在TControl
中。所以我不确定在非通用实现中会有这么多重复的代码。
我怀疑非泛型版本会产生更少的代码和RTTI,因为当前的泛型实现往往不会复制源,但会增加exe大小。
恕我直言,基于泛型的设计将为实现添加更多抽象,但非泛型可能更接近它将适应的VCL层次结构。
因此,对于您的特定情况(映射VCL),由于您尝试映射非泛型类,我宁愿调查非泛型解决方案。
对于另一个(非基于VCL的)适配器架构,我可能会从下到上建议一个纯通用实现。