代码之家  ›  专栏  ›  技术社区  ›  Ken Bourassa

模板(或其他技术)是否支持以下构造?

  •  1
  • Ken Bourassa  · 技术社区  · 14 年前

    这是我的后续行动 other question

    当我第一次听说泛型的时候,是在Delphi2009发布之前(在Delphi2009发布之前,他们首先介绍了泛型)。我知道在那之前.Net支持它,但是我还没有深入到这个领域。

    通过阅读泛型,我了解到它允许类对它有一个变量参数,然后通过类的所有代码替换传递给它的任何值。

    描述泛型的方式(或者至少,我理解泛型允许的方式)是,给定以下声明:

    procedure TMyClass<T>.Init;
    begin
      FField := T.Create(nil);
    end;
    

    我以为会有用的。我假设编译失败的地方如下:

    begin
      TMyClass<TComponent>.Create; //Works correctly
      TMyClass<TObject>.Create;  //Doesn't work, as even though it HAS a constructor, it has none that receive a single pointer parameter
      TMyClass<string>.Create; //Doesn't work, not an object. 
    end;
    

    现在,我知道我错了。所以,我现在想知道的是,是否有一种技术/语言特性可以支持这样的构造。也许是代码模板?其他编程语言中的泛型?或者别的什么?

    4 回复  |  直到 7 年前
        1
  •  1
  •   Puppy    14 年前

    现在,我知道我错了。那么,什么 技术/语言特性 支持这样的结构。代码 也许是模板?其他中的泛型 编程语言?或者也许 还有别的吗?

    C中的泛型有你想要的能力。C++中的模板更强大——通过模板生成的代码与手工编写的代码完全相同,除了它们只能编译成内联的部分,这是很吸引人的。

        2
  •  1
  •   Jeroen Wiert Pluimers    14 年前

    @游戏猫,你不能 TObject 作为一个约束,但是你可以 class 托宾 约束)。

    请注意,无论您使用 托宾 ,您不能调用 Create 没有技巧的参数。

    例1: 约束条件:

    unit Unit1;
    
    interface
    
    uses
      Classes;
    
    type
      TMyClass<T: class, constructor> = class
      strict private
        FField: T;
      public
        procedure Init;
      end;
    
    implementation
    
    procedure TMyClass<T>.Init;
    begin
      FField := T.Create();
    end;
    
    end.
    

    例2: TComponent 创建

    unit Unit2;
    
    interface
    
    uses
      Classes;
    
    type
      TMyClass<T: TComponent, constructor> = class
      strict private
        FField: T;
      public
        procedure Init;
      end;
    
    implementation
    
    procedure TMyClass<T>.Init;
    var
      ComponentClass: TComponentClass;
    begin
      ComponentClass := T;
      FField := ComponentClass.Create(nil);
    end;
    
    end.
    

    约束,也可以有记录约束。 有了这个,你需要 Default

    unit Unit3;
    
    interface
    
    uses
      Classes;
    
    type
      TMyClass<T: record> = class
      strict private
        FField: T;
      public
        procedure Init;
      end;
    
    implementation
    
    procedure TMyClass<T>.Init;
    begin
      FField := Default(T);
    end;
    
    end.
    

    希望对泛型和约束有一些启发。

    --杰罗恩

        3
  •  0
  •   Toon Krijthe Paul    14 年前

    可以对泛型类型设置约束。如果你想使用这种类型的某些方面,你需要这个。例如方法。

    如果要调用构造函数,则需要在类约束旁边提供constructor约束:

    type
      TMyClass<T: TComponent, constructor> = class
        // ..
      end;
    
    procedure TMyClass<T>.Init;
    begin
      FField := T.Create(nil);
    end;
    

    不幸的是TObject不是一个有效的约束。(据Delphi XE报道)。

    这可能有风险,甚至毫无意义。如果在泛型上调用方法X,并用不支持方法X的类实例化它,那么正确的行为是什么。。。

        4
  •  0
  •   Jeroen Wiert Pluimers    14 年前

    历史上,原生Delphi没有这样的类型系统(NET有,Delphi Prism中的泛型支持它,就像C#和VB.NET一样)。

    解决这个问题是困难的; Allen Bauer gave it a shot implementing a Nullable type ,并且他必须进行一些严重的扭曲,以便仅实现Equals(=)和NotEquals(<gt;)运算符行为,从而同时涵盖引用类型和值类型。

    因此,支持这些计划将很困难,但可能是可行的:

    begin
      TMyClass<TComponent>.Create; //Works correctly
      TMyClass<TObject>.Create;  //Doesn't work, as even though it HAS a constructor, it has none that receive a single pointer parameter
      TMyClass<string>.Create; //Doesn't work, not an object.
    end;