2类类型的通用比较函数

时间:2014-01-22 10:37:36

标签: delphi generics

这里使用Delphi的通用编程功能来定义Vertex类和图形类:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  System.Math, System.Generics.Collections,
  System.Generics.Defaults, Vcl.StdCtrls;

type

  tvertex = class(TObject)
    name: string;
    function markme: tvertex;
    function Compare(const v: TVertex): Integer;
    constructor create;
    destructor free;
  end;

  tvertex<T> = class(tvertex)
    Userdata: T;
  end;

  TGraph <T : class > = class (Tobject)
      vertexlist :  TObjectList<T>;

      procedure CompareLists(
      var _V1: TObjectList<T>;
      var _V2: TObjectList<T>);
  end;




  TForm1 = class(TForm)
    Edit1: TEdit;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

  // helper function
function createVertexComparer(): IComparer <TVertex  >;

implementation

// helper functions
function createVertexComparer(): IComparer<TVertex>;
begin
  Result := TDelegatedComparer<TVertex>.Create(
    function(const Left, Right: TVertex): Integer
    begin
      Result := Left.Compare(Right);
    end);

end;




{$R *.dfm}
{ tvertex }

function tvertex.Compare(const v: TVertex): Integer;
begin
    // ...
end;

constructor tvertex.create;
begin
  // ...
end;

destructor tvertex.free;
begin
  // ...
end;

function tvertex.markme: tvertex;
begin
  // ...
end;



procedure TGraph<T>.CompareLists(
var _V1: TObjectList<T>;
var _V2: TObjectList<T>);
begin
     _V1 := TObjectList<T>.Create(createVertexComparer(), False);  /// line which does not compile ....
end;

end.

如何修改他愿意接受TVertexTVertex<T>类类型作为参数的代码....

1 个答案:

答案 0 :(得分:2)

我想说你遇到的主要问题是你声明了这样的图形类:

type
  TGraph<T: class>
    ...
  end;

这意味着编译器将接受任何类T。因此,图表类对T一无所知,除此之外它是一个类。

很难确定,但我认为你打算T成为一个顶点。所以你需要适当地约束图类。

type
  TGraph<T: TVertex>
    ...
  end;

然后你有这个功能的另一个问题:

function createVertexComparer(): IComparer<TVertex>;

您将结果传递给

TObjectList<T>.Create

但是这需要IComparer<T>类型的参数,而您提供的是IComparer<TVertex>。这是编译器报告的类型不匹配。

您需要将createVertexComparer作为TGraph<T>的方法,以便它可以是通用的。它的实施将是:

function TGraph<T>.createVertexComparer(): IComparer<T>;
begin
  Result := TDelegatedComparer<T>.Create(
    function(const Left, Right: T): Integer
    begin
      Result := Left.Compare(Right);
    end);
end;

另外,请注意

destructor free;

等待发生的灾难。你必须使用

destructor Destroy; override;

事实上,你的其余代码让我很烦恼。例如:

procedure TGraph<T>.CompareLists(var _V1, _V2: TObjectList<T>);
begin
  _V1 := TObjectList<T>.Create(createVertexComparer(), False);
end;

方法的名称与它的名称不匹配。它只返回一个值,为什么有两个var参数?在查看这样的代码时很难辨别意图。