Повторение процедуры для каждого предмета в классе - PullRequest
2 голосов
/ 13 апреля 2010
  Data.XX.NewValue := Data.XX.SavedValue;
  Data.XX.OldValue := Data.XX.SavedValue;

Мне нужно выполнить вышеописанное большое количество раз, где XX представляет значение в классе. Притворяться, что в списке было 3 предмета: Тим, Боб, Стив. Есть ли способ сделать вышеперечисленное для всех трех человек, не вводя вышеуказанный код три раза?

(Данные - это класс, содержащий несколько объектов, каждый тип TList, которые содержат OldValue, NewValue и SavedValue)

Ответы [ 4 ]

4 голосов
/ 13 апреля 2010

Что бы я сделал, если бы мне пришлось сделать что-то подобное, это поместить еще один TList в Data, который содержит список всех объектов в нем. Заполните его в конструкторе, а затем, когда вам нужно сделать что-то подобное, используйте цикл, чтобы применить одну и ту же базовую операцию к каждому элементу в списке.

0 голосов
/ 14 апреля 2010

Судя по этому посту и этому посту , я бы предложил следующее:

unit MyAssignment;

interface

  type
    TValueKind = ( EconomicGrowth,
                   Inflation,
                   Unemployment,
                   CurrentAccountPosition,
                   AggregateSupply,
                   AggregateDemand,
                   ADGovernmentSpending,
                   ADConsumption,
                   ADInvestment,
                   ADNetExports,
                   OverallTaxation,
                   GovernmentSpending,
                   InterestRates,
                   IncomeTax,
                   Benefits,
                   TrainingEducationSpending );

        TValue = record
          NewValue,
          OldValue,
          SavedValue : Double;

          procedure SetValue( aVal : Double );
          procedure SaveValue();
          procedure RestoreValue();
        end;

        TDataArray = array [TValueKind] of TValue;

        var
          Data : TDataArray;

implementation

    {TValue}

  procedure TValue.SetValue( aVal : Double );
  begin
    OldValue := NewValue;
    NewValue := aVal;
  end;

  procedure TValue.SaveValue;
  begin
    SavedValue := NewValue;
  end;

  procedure TValue.RestoreValue;
  begin
    NewValue := SavedValue;
    OldValue := SavedValue;
  end;


end.

Теперь вы можете написать такой код:

            //accessing the values :
            // Data[XX] instead of Data.XX

            //examples :
          ShowMessage(FloatToStr(Data[Inflation].SavedValue));
          Data[AgregateSupply].SetValue( 10.0 );
          Data[Benefits].SaveValue;

          //writing loops :
        procedure RestoreValues( var aData : TDataArray ); //the "var" keyword is important here : google "arguments by value" "arguments by reference"
          var
            lKind : TValueKind;
        begin
          for lKind := Low(TValueKind) to High(TValueKind) do
            aData[lKind].RestoreValue;
        end;

        procedure SaveValues( var aData : TDataArray );
          var
            lKind : TValueKind;
        begin
          for lKind := Low(TValueKind) to High(TValueKind) do
            aData[lKind].RestoreValue;
        end;

          //calling these functions :
        SaveValues( Data );
        RestoreValues( Data );

Если вам нужны более сложные манипуляции с массивом, было бы неплохо поместить его в класс - заменить поля, которые вы записали, только в поле типа TDataArray - и написать функции для манипулирования данными в виде методов этот класс.

0 голосов
/ 14 апреля 2010

Может быть, я не понимаю, все в порядке, но ... Вот где сияет объектно-ориентированное. Вы определяете процедуру для класса и затем применяете для любого создаваемого вами экземпляра.

TMyPropValue = class(TObject)
private
  FNewValue: double;   
  FOldValue: double;
  procedure SetValue(AValue: double);
public
  procedure RestoreOldValue;
  propety NewValue: double read FNewValue write SetValue;   // Raed/write property (write using a procedure)
  property OldValue: double read FOldValue;   // Read only property
end;

TMyClass = class(TObject)
private
  FProp1: TMyPropValue;
  FProp2: TMyPropValue;
public
  procedure RestoreValues;
end;

//....

var
  MyObj1: TMyClass;
  MyObj2: TMyclass;

procedure TMyPropValue.SetValue(AValue: double);
begin
  FOldValue := FNewValue;
  FNewValue := AValue;  
end;

// Restore the Old value of this Prop
procedure TMyPropValue.RestoreOldValue;
begin
  FNewValue := FOldValue;  
end;

// Restore ald the Values of the class
procedure TMyClass.RestoreValues;
begin
  FProp1.RestoreOldValue;
  FProp2.RestoreOldValue;
end;
// -----------

// Creating and populating a couple of objects (instances)
procedure XXX;
begin
  MyObj1 := TMyClass.Create;
  MyObj1.Prop1.NewValue := 10.25:
  MyObj1.Prop2.NewValue := 99.10:

  MyObj2 := TMyClass.Create;
  MyObj2.Prop1.NewValue := 75.25:
  MyObj2.Prop2.NewValue := 60.30:
end;

// Changing values, the class internaly will save the OldValue
procedure yyyy;
begin
  MyObj1.Prop1.NewValue := 85.26:
  MyObj1.Prop2.NewValue := 61.20:

  MyObj2.Prop1.NewValue := 99.20:
  MyObj2.Prop2.NewValue := 55.23:
end;

// Using a procedure from the class
procedure zzzz;
begin
  MyObj1.RestoreValues;
  MyObj2.RestoreValues;
end;

Надеюсь, что это поможет Daniel

0 голосов
/ 13 апреля 2010

Я был бы здесь осторожен. Я знаю, что соблазн будет использовать общий интерфейс и рефлексию, или какую-то другую автоматизацию, которая будет более гибкой и, честно говоря, более увлекательной для написания. Избегайте этого искушения. Нет ничего плохого в том, чтобы перечислять каждый элемент в списке согласно вашему образцу. Шаблоны хороши, и код будет удобочитаемым, простым в исполнении и легко изменяющим любое отдельное свойство, которое не соответствует шаблону.

Низкотехнологичный способ избежать распечатки - использовать нашего старого друга Excel. Поместите все свои свойства в столбец A, а затем используйте эту формулу в столбце B:

=  CONCATENATE("Data.", A1, ".NewValue := Data.", A1, ".SavedValue;", CHAR(10), "Data.", A1, ".OldValue := Data.", A1, ".SavedValue;", CHAR(10))
...