Delphi 引用具有不同变量的例程
是否可能对单个例程有两个引用,即以某种方式组合这些引用:Delphi 引用具有不同变量的例程,delphi,Delphi,是否可能对单个例程有两个引用,即以某种方式组合这些引用: procedure SetUpGrid(AGrid: TStringGrid); procedure SetUpGrid(AGrid: TJVStringGrid); procedure SetUpGrid(AGrid: ??); Begin ... 将有两个过程,但这一个过程相同且冗长,只需要在其他过程中使用不同的网格。是的,如果两个过程都有公开所有所需功能的公共网格。即如果两者都是TCustomGrid的后代,则使用过程SetU
procedure SetUpGrid(AGrid: TStringGrid);
procedure SetUpGrid(AGrid: TJVStringGrid);
procedure SetUpGrid(AGrid: ??);
Begin
...
将有两个过程,但这一个过程相同且冗长,只需要在其他过程中使用不同的网格。是的,如果两个过程都有公开所有所需功能的公共网格。即如果两者都是
TCustomGrid
的后代,则使用过程SetUpGrid(agid:TCustomGrid)代码>
当然,由于所有对象都是从TObject派生出来的,所以您可以使用它,但它有些无用,因为TObject不会公开网格的任何属性/方法。。。您必须测试实际类型的输入,如
procedure SetUpGrid(AGrid: TObject);
begin
if(AGrid is TStringGrid)then begin
...
end else if(AGrid is TJVStringGrid)then begin
...
end
end
这在某种程度上取消了只使用一个过程的想法。如果TStringGrid和TJvStringGrid在某种程度上是“相关的”,即具有相同的基类,或者一个继承自另一个,那么它就相当简单。将该类型用作参数类型
如果不是这样,那就不那么容易了。泛型对您没有帮助,使用utmostbase类,TObject也没有任何帮助,因为它没有您需要的方法
解决方案一
您可能会幸运地使用匿名方法,并将这些方法用作函数的参数,以便可以在函数内部调用它们:
type
TGridFunc = reference to function: Integer;
procedure SetupGrid(AGridFunc: TGridFunc);
var
...
begin
...
Error := AGridFunc;
...
end;
您可以这样使用它:
var
GF: TGridFunc;
JvGrid: TJvStringGrid;
VclGrid: TStringGrid;
begin
...
SetupGrid(
function: Integer
begin
... do things with JvGrid ...
Result := 0;
end);
SetupGrid(
function: Integer
begin
... do things with VclGrid ...
Result := 1;
end);
...
end;
这有点复杂,让人想起依赖注入,但我看不到其他方法
解决方案二
哦,等等,还有另一种方法:定义一个接口类型(比如说IStringGrid),它包含您可能需要的所有方法。实现两次,一次作为TJvStringGrid的后代,一次作为TStringGrid的后代,包装正确类型的现有网格。SetupGrid看起来像:
procedure SetupGrid(Grid: IStringGrid);
现在,您可以将这些实现传递给SetupGrid:
SetupGrid(TStringGridWrapper.Create(Form1.StringGrid1));
SetupGrid(TJvStringGridWrapper.Create(Form2.JvStringGrid1));
当然,只有当您可以重用这些包装器,或者如果SetupGrid非常复杂,您不想简单地编写两次,这才有意义。瞧,只要值得这么麻烦
更新
我刚刚检查过,显然TJvStringGrid继承自TJvExStringGrid,它继承自VCL中的TStringGrid。所以现在很容易:
procedure SetupGrid(AGrid: TStringGrid);
begin
...
// things that equally apply to TStringGrid and TJvStringGrid can be done here.
if AGrid is TJvStringGrid then
begin
...
// things that only apply to TJvStringGrid can be done here.
...
end;
...
end;
当然,TStringGrid和TJvStringGrid的单位必须同时位于该单位实施部分的uses子句或界面部分。我怀疑TJvStringGrid
来自绝地VCL。在这种情况下,它是TJvExStringGrid
的后代,TJvExStringGrid是TStringGrid
的直接后代,当一个类(TJvStringGrid)从另一个类(TStringGrid)派生时,您无需执行任何特殊操作
您可以使用最常见的类(在本例中为TStringGrid)声明您的过程:
procedure SetUpGrid(AGrid: TStringGrid);
并将TJvStringGrid的一个实例传递给它
例如:
procedure SetUpGrid(AGrid: TStringGrid);
begin
// Whatever your code does to set up the grid.
end;
procedure TForm1.SomeGridToSetup;
var
ASimpleTStringGrid: TStringGrid;
AJediVclStringGrid: TJvStringGrid;
begin
ASimpleTStringGrid := TStringGrid.Create(Self);
AJediVclStringGrid := TJvStringGrid.Create(Self);
SetUpGrid(ASimpleTStringGrid);
SetUpGrid(AJediVclStringGrid);
end;
我保留了原始内容,因为我认为其他解决方案适用于两个类不共享其祖先的情况。