вторник, 1 февраля 2011 г.

Введение в обобщенное программирование (Generics) - 3

Использование обобщений в разных конструкциях языка
Итак, мы разобрали применение обобщений в классах, однако роль обобщений на этом не заканчивается, помимо применения в классах обобщения могут использоватся и в других конструкциях языка:
Обобщения в записях

Ниже приведен пример использование обобщений в записи:
program GenericInRecord;

uses
  SysUtils;
type
  TPoint  = Record
                             x, y, z: T_Coordinate;
                           end;

var
  center: TPoint;
  projection: TPoint;

begin
  center.x := 100;
  projection.x := 3.1415;
  writeln(center.x);
  writeln(projection.x);
  write('type enter');
  Readln;
end.

Обобщения в массивах

program GenericInArray;
uses
  SysUtils;

type
  CellArray = Array of T_Cell;
  CoordArray = Array of Array of T_Coordinate;
  AverageArray = Array [1 .. 5] of T_Value;

var
  index: Integer;
  Counts  : CellArray;   // одномерный массив Integer
  Measures: CellArray;    // одномерный массив Double
  Coord: CoordArray;      // Многомерный массив Double
  Doubles: Array of Double;       // Обычный массив
begin
  SetLength(Counts, 100);
  for index := 0 to 99 do
    Counts[index] := Random(100);

  SetLength(Measures, 20);
  for index := 0 to 19 do
    Measures[index] := 3.14 * Random;

  SetLength(Coord, 10, 20);
  Coord[2, 3] := 3.14;
  
  // cмещение обобщенных массивов и обычных массивов
  SetLength(Doubles, 10 * 20);
  Doubles[2 * 10 + 3] := Coord[2, 3];

  write('type enter');
  Readln;
end.

Обобщения в процедурных типах
Мы можем использовать параметр типа в определении процедурных типов:

unit GenericProcType;

interface

Type
 THandleTwo  = Procedure(one, two: T);

implementation

end.

После чего мы могли бы, имея одно обобщенное описание процедуры, выбирать для разных типов Integer и Double – разные процедуры, в которых позже производить разные арифметические операции:
procedure ConvertTwoInteger(value, rate: Integer);
begin
  writeln(value, ' div ', rate, ' = ', value Div rate);
end;

procedure ConvertTwoDouble(value, rate: Double);
begin
  writeln(value, ' / ', rate, ' = ', value / rate);
end;

procedure UseBinaryOperator;
var
  twoInteger: THandleTwo;  // Обобщенный процедурный тип
  twoDouble : THandleTwo;
begin
  twoInteger := ConvertTwoInteger;
  twoInteger(20, 3);     // выполняем процедуру с параметрами Integer

  twoDouble := ConvertTwoDouble;
  twoDouble(20.0, 3.0);  // выполняем процедуру с параметрами Double
end;
Процедурные типы обычно используются для применения некоторых манипуляции с множеством значений. Например, определив описанием процедурного типа стандартные правила обработки, можно во время выполнения программы указывать какие конкретные процедуры будут вызываться для отработки:

Следующий пример показывает список значений с общей процедурой обработки:

unit ApplyProcType;

interface

Type
  THandleOne = Function(Value: T): T;

  TVector = Class
    ArrVector: Array [0 .. 9] of T;
    constructor Create;
    procedure Compute(vHandleOne: THandleOne);
    procedure DisplayVector;
  end;

implementation

uses SysUtils;

constructor TVector.Create;
begin
  Inherited;
end;

procedure TVector.Compute(vHandleOne: THandleOne);
var
  index: Integer;
begin
  for index := 0 to 9 do
    ArrVector[index] := vHandleOne(ArrVector[index]);
end;

procedure TVector.DisplayVector;
var
  index  : Integer;
  result : String;
begin
  {   // Для Delphi.Net раскоментируйте
  result := '';
  for index := 0 to 9 do
      result := result + ArrVector[index].ToString + ' ';
  writeln(result);
  }
end;

Использовать данный список можно так:

function IntegerSquare(value: Integer): Integer;
begin
  Result := value * value;
end;

procedure UseVector;
var
  vector: Tvector;
  index: Integer;
begin
  vector := Tvector.Create;
  for index := 0 to 9 do
      vector.ArrVector[index] := index;
  vector.DisplayVector;

  vector.compute(IntegerSquare); // Передаем процедуру
  vector.DisplayVector;
end;

Продолжение следует...







Комментариев нет:

Отправить комментарий