Будут ли шаблоны (или другие технологии) поддерживать следующую конструкцию? - PullRequest
1 голос
/ 23 октября 2010

Это своего рода продолжение моего другого вопроса .

Когда я впервые услышал о дженериках, это было до выхода Delphi 2009 (где они впервые его представили),Я знаю, что до этого она поддерживалась в .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 ]

1 голос
/ 23 октября 2010

Теперь я хорошо знаю, что был неправ. И что Интересно сейчас, есть ли технология / языковая функция, которая бы поддержать такую ​​конструкцию. Код шаблоны возможно? Дженерики в других языки программирования? Или, может быть что-то еще?

Дженерики в C # обладают той силой, которая вам нужна. Шаблоны в C ++ еще сильнее - код, сгенерированный с помощью шаблона, идентичен коду, написанному от руки, за исключением той части, где они могут быть скомпилированы только inline, что отстой.

1 голос
/ 23 октября 2010

@ Gamecat, вы не можете иметь TObject в качестве ограничения, но вы можете иметь class в качестве ограничения (которое прекрасно покрывает это отсутствие TObject ограничения).

Обратите внимание, что независимо от того,вы используете TObject или class, вы не можете вызвать Create с параметром без уловки.

Пример 1: class ограничение:

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 в качестве ограничения и параметр в Create

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.

В дополнение к ограничению class вы также можете иметь ограничение записи.Для этого вам понадобится 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.

Надежда, которая проливает некоторый свет на обобщенные элементы и ограничения.

- jeroen

0 голосов
/ 23 октября 2010

@ Кен: для того, чтобы код, подобный тому, который вы запрашивали, работал по-настоящему универсальным образом, вам необходимо иметь унифицированную систему типирования, которая объединяет как ссылочные типы (классы), так и типы значений (строки, целые числа и т. Д.). 1001 *

Исторически, у родного Delphi нет такой системы ввода (.NET имеет, и дженерики в Delphi Prism поддерживают ее, как это делают C # и VB.NET).

Обойти это сложно; Аллен Бауэр дал ему шанс реализовать тип Nullable , и ему пришлось сделать серьезный поворот, чтобы реализовать только поведение оператора Equals (=) и NotEquals (<>) таким образом, чтобы охватывать как ссылку, так и значение. типы.

Так что поддерживать их будет сложно, но, вероятно, выполнимо:

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;

- Йерун

0 голосов
/ 23 октября 2010

Вы можете наложить ограничения на универсальный тип.Вам это нужно, если вы хотите использовать определенные аспекты этого типа.Например, метод.

Если вы хотите вызвать конструктор, вам нужно указать ограничение consructor рядом с ограничением класса:

type
  TMyClass<T: TComponent, constructor> = class
    // ..
  end;

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

К сожалению, TObject не является допустимым ограничением.(согласно Delphi XE).

Теперь я хорошо знаю, что был неправ.Итак, что мне сейчас интересно, есть ли технология / язык>, которая бы поддерживала такую ​​конструкцию.Шаблоны кода возможно?Обобщения в других> языках программирования?Или может что-то еще?Это может быть рискованно или даже бессмысленно.Если вы вызываете метод X для универсального объекта и создаете его экземпляр с помощью класса, который не поддерживает метод X, каково правильное поведение ...

...