是否可以对单个例程进行2次引用,即以某种方式组合这些:
procedure SetUpGrid(AGrid: TStringGrid);
procedure SetUpGrid(AGrid: TJVStringGrid);
procedure SetUpGrid(AGrid: ??);
Begin
...
会有两个程序,但这个程序是相同且冗长的,只需要使用不同的网格进行其他程序。
答案 0 :(得分:1)
我怀疑TJvStringGrid
来自Jedi VCL。在这种情况下,它是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;
答案 1 :(得分:0)
是的,如果两者都有共同的安慰剂,它会暴露您需要的所有功能。即如果两者都是TCustomGrid
的后代,则使用procedure SetUpGrid(AGrid: TCustomGrid);
当然,由于所有对象都来自TObject,你可以使用它但是它有点无用,因为TObject不会暴露网格的任何属性/方法......你必须测试实际类型的输入像
procedure SetUpGrid(AGrid: TObject);
begin
if(AGrid is TStringGrid)then begin
...
end else if(AGrid is TJVStringGrid)then begin
...
end
end
这有点取消了只使用一个程序的想法。
答案 2 :(得分:0)
如果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如此复杂以至于你不想只编写两次它,这才有意义。 IOW,只有值得这么麻烦。
我刚检查过,显然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子句或单元的接口部分。