Repeating procedure for every item in class
Data.XX.NewValue := Data.XX.SavedValue;
Data.XX.OldValue := Data.XX.SavedValue;
开发者_JAVA百科
I need to do the above a large number of times, where XX represents the value in the class. Pretending there were 3 items in the list: Tim, Bob, Steve. Is there any way to do the above for all three people without typing out the above code three times?
(Data is a class containing a number of Objects, each type TList, which contain OldValue, NewValue and SavedValue)
What I'd do if I had to do something like this is put one more TList on Data, which holds a list of all the Objects on it. Fill it in the constructor, and then when you have to do something like this, use a loop to apply the same basic operation to each item in the list.
Maybe I'm not understanding it ok but... Here is where Object Oriented shines. You define a procedure for the class and then apply for any instance you create.
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;
Hope this help Daniel
Judging from this post and this post, I would suggest the following :
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.
Now you can write this kind of code :
//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 );
If you need more complex manipulations on the array, it would be a good idea to put it into a class - replace the fields you wrote with only on efield of type TDataArray - and write the functions to manipulate the data as methods of this class.
I would be careful here. I know the temptation is going to be to use a common interface and reflection, or some other automation that is more flexible and, frankly, more fun to write. Avoid this temptation. There is nothing wrong with listing every item in the list out according to your pattern. Patterns are good, and the code will be readable, easy to execute, and easy to modify any individual property that does not fit the pattern.
The low tech way to avoid typing everything out is to use our old friend Excel. Put all your properties in Column A, and then use this formula in column B:
= CONCATENATE("Data.", A1, ".NewValue := Data.", A1, ".SavedValue;", CHAR(10), "Data.", A1, ".OldValue := Data.", A1, ".SavedValue;", CHAR(10))
精彩评论