Структура Delphi Generics Class - PullRequest
2 голосов
/ 11 января 2011

Я новичок в дженериках и мне нужна помощь в структурировании класса и реализации методов.

Я пытаюсь использовать дженерики для сериализации любого TObject -JSON.Более того, я хочу иметь возможность повторно использовать код.

Это мои вопросы:

  1. Как создать универсальный конструктор?Я хочу иметь возможность использовать Self или Default(T), но он возвращает только nil.

  2. V := Marshal.Marshal(ReturnObject) - Этот метод требует TObject, но я не знаю, как ссылаться на текущий объект, который был передан.

  3. Как я могу использовать это внутри метода?Посмотрите на приведенный ниже код, помеченный как « Вопрос 3 ».

Это мой код:

TFileOperationResult = class(TObject)
private
  FSuccess: Boolean;
  //Error: PException;
  FLastError: Integer;
  function GetFailure: Boolean;
  property Failure: Boolean read GetFailure;
public
  property Success: Boolean read FSuccess write FSuccess;
  property LastError: Integer read FLastError write FLastError;
end;

TResponseObject<T: class> = class(TObject)
private
  FReturnObject: T;
  function GetReturnObject: T;
  function BaseStringsConverter(Data: TObject): TListOfStrings;
public
  constructor Create; overload;
  property ReturnObject: T read GetReturnObject;
  procedure Serialize;
end;

constructor TResponseObject<T>.Create;
begin
 // Question 1 - What should go in here?
end;

function TResponseObject<T>.GetReturnObject: T;
begin
  Result := Default(T);// Is this correct?
end;

procedure TResponseObject<T>.Serialize;
var
  Marshal: TJSONMarshal;
  V: TJSONValue;
begin
  Marshal := TJSONMarshal.Create(TJSONConverter.Create);
  Marshal.RegisterConverter(TResponseObject<T>, BaseStringsConverter);
  V := Marshal.Marshal(ReturnObject); // Question 2 - How Can I refer to 'Self'?
  OutPut := V.ToString;
  Marshal.Free;
end;

Телефонный код:

procedure TForm1.Test;
var
  FileOperationResult: TResponseObject<TFileOperationResult>;
begin
  FileOperationResult := TResponseObject<TFileOperationResult>.Create;
  FileOperationResult.Serialize;
end;

Вопрос 3:

procedure TForm1.MoveCopyFile<THowNowResponse>(ASource, DDestination: String);
var
  FileOperationResult: TFileOperationResult;
begin
  FileOperationResult := TFileOperationResult.Create;
  // What to do?
end;

Любые другие комментарии приветствуются.

1 Ответ

1 голос
/ 11 января 2011

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

constructor TResponseObject<T>.Create(value: T);
begin
  FReturnObject := value;
end;

Аналогично, если вы создаете метод GetReturnObject, он, вероятно, должен возвращать значение поля FReturnObject. (Или вы можете сделать так, чтобы read аксессор свойства просто ссылался на FReturnObject напрямую.)

function TResponseObject<T>.GetReturnObject: T;
begin
  Result := FReturnObject;
end;

На самом деле трудно ответить на вопрос № 3, поскольку я не знаю, что вы пытаетесь с этим сделать, но, надеюсь, мои ответы на первые два вопроса помогут вам вернуться на правильный путь. Просто помните, что дженерики не должны сбивать с толку; в основном это просто замена типа. Где бы вы ни использовали обычный тип в неуниверсальной подпрограмме, вы можете заменить его на <T> для создания универсальной подпрограммы, а затем заменить любой тип, который соответствует ограничениям для этого конкретного T.

...