引用具有不同变量的例程

时间:2011-07-16 13:07:10

标签: delphi

是否可以对单个例程进行2次引用,即以某种方式组合这些:

procedure SetUpGrid(AGrid: TStringGrid);
procedure SetUpGrid(AGrid: TJVStringGrid);


procedure SetUpGrid(AGrid: ??);
Begin
...

会有两个程序,但这个程序是相同且冗长的,只需要使用不同的网格进行其他程序。

3 个答案:

答案 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子句或单元的接口部分。