我正在使用Delphi 2010,我有一个单元,多年来我添加了自己的程序和功能,可以用于我所做的任何项目,例如:
function ListBoxIsSelected(ListBox: TListBox): Boolean;
begin
Result:= ListBox.ItemIndex <> -1;
end;
以上使用TListBox
作为参数,因此无论何时使用上述函数,我都必须提供listbox
类的TListBox
。
现在假设我有一些其他组件库可以使用相同的函数,例如Jedi组件类。
当Jedi listbox
为TJvListBox
类并且我的函数正在寻找TListBox
类时,我怎么能使用上面的函数?虽然两个组件实际上是相同的,但类名是不同的。如果我专门为TJvListBox
提供了相同的功能,它可能会起作用,因为它们都是“列表框”:
function ListBoxIsSelected(ListBox: TJvListBox): Boolean;
begin
Result:= ListBox.ItemIndex <> -1;
end;
现在,我需要将组件作为参数传递,以相同的方式编写完整的过程和函数。只是为了使用不同的组件类而不得不重写它们是不可行的!
我如何用泛型来写这个?
答案 0 :(得分:9)
你不能用泛型来写,除非你的目标类当然都来自同一个基类。 (但那时你不需要泛型。)
如果你真的想要能够检查任何对象上的ItemIndex属性&lt;&gt;但是,您可以使用不同的Delphi 2010功能:扩展RTTI。
uses
SysUtils, RTTI;
function IsSelected(item: TObject): boolean;
var
context: TRttiContext;
cls: TRttiType;
prop: TRttiProperty;
ItemIndex: integer;
begin
if item = nil then
raise Exception.Create('Item = nil');
context := TRttiContext.Create;
cls := context.GetType(item.ClassType);
prop := cls.GetProperty('ItemIndex');
if prop = nil then
raise Exception.Create('Item does not contain an ItemIndex property.');
ItemIndex := prop.GetValue(item).AsInteger;
result := ItemIndex <> -1;
end;
但是要小心。这里没有编译时类型检查,这个过程明显慢于原始例程。你可能不会注意到它,但是如果你在紧密的循环中调用这样的东西,它会减慢速度。
答案 1 :(得分:2)
我不明白我怎么能用Generics写这个?
你不能 - 除非你的组件实现了一个公共接口,或者从一个带有标准ListBox
的公共基类继承,并且该接口/基类提供了ItemIndex
属性。
事实上,这个用例并不是泛型的一个很好的例子,因为在声明中使用接口或基类也可以正常工作。
答案 2 :(得分:0)
在这种情况下,您可以编写两个重载函数,一个期望TJvListBox,另一个期望TListBox。
在更复杂的情况下,这种方法可能不太适用,但我认为您的案例对于此解决方案来说足够简单。
答案 3 :(得分:0)
我现在无法查找(节假日,没有Delphi),但TJvListBox和TListBox不是从一个共同的祖先下降(我的猜测是:TCustomListBox)?在这种情况下,这样的事情应该有效:
interface
function TListBox_IsItemSelected(_ListBox: TCustomListBox): boolean;
implementation
function TListBox_IsItemSelected(_ListBox: TCustomListBox): boolean;
begin
Result := _ListBox.ItemIndex <> -1;
end;
以防万一ItemIndex(正如我所说:我现在无法检查)在TCustomListBox中受到保护,你只能使用一个类型攻击:
type
TListBoxHack = class(TCustomListBox)
end;
function TListBox_IsItemSelected(_ListBox: TCustomListBox): boolean;
begin
Result := TListBoxHack(_ListBox).ItemIndex <> -1;
end;
(我以为我应该提一下,因为原来的问题已经回答了:使用Generics在这里没有帮助。)