Binäre Operationen implementieren
Nach oben zu Eine Klasse zur Aktivierung des selbstdefinierten Variant-Typs erzeugen
Damit der selbstdefinierte Variant-Typ mit den in der System-Unit aufgeführten binären Standardoperatoren (+, -, *, /, div, mod, shl, shr, and, or, xor) arbeiten kann, müssen Sie die Methode BinaryOp überschreiben. BinaryOp
besitzt drei Parameter: den Wert des linken Operanden, den Wert des rechten Operanden sowie den Operator. Implementieren Sie diese Methode zur Ausführung der Operation und geben Sie das Ergebnis mit derselben Variablen zurück, die den linken Operanden enthielt.
Die folgende BinaryOp
-Methode stammt z.B. von TComplexVariantType
(definiert in der Unit System.VarCmplx):
Delphi:
procedure TComplexVariantType.BinaryOp(var Left: TVarData; const Right: TVarData;
const Operator: TVarOp);
begin
if Right.VType = VarType then
case Left.VType of
varString:
case Operator of
opAdd: Variant(Left) := Variant(Left) + TComplexVarData(Right).VComplex.AsString;
else
RaiseInvalidOp;
end;
else
if Left.VType = VarType then
case Operator of
opAdd:
TComplexVarData(Left).VComplex.DoAdd(TComplexVarData(Right).VComplex);
opSubtract:
TComplexVarData(Left).VComplex.DoSubtract(TComplexVarData(Right).VComplex);
opMultiply:
TComplexVarData(Left).VComplex.DoMultiply(TComplexVarData(Right).VComplex);
opDivide:
TComplexVarData(Left).VComplex.DoDivide(TComplexVarData(Right).VComplex);
else
RaiseInvalidOp;
end
else
RaiseInvalidOp;
end
else
RaiseInvalidOp;
end;
In dieser Implementierung sind mehrere Punkte erwähnenswert:
Diese Methode behandelt nur den Fall, dass der Variant rechts des Operators ein selbstdefinierter Variant-Typ ist, der eine komplexe Zahl darstellt. Ist der linke Operand eine komplexe Zahl und der rechte nicht, erzwingt der komplexe Variant, dass der rechte Operand zuerst in einen komplexen Variant umgewandelt wird. Dazu wird die Methode RightPromotion so überschrieben, dass sie den Typ stets in der Eigenschaft VarType
benötigt.
Delphi:
function TComplexVariantType.RightPromotion(const V: TVarData;
const Operator: TVarOp; out RequiredVarType: TVarType): Boolean;
begin
{ Komplexer Op TypeX }
RequiredVarType := VarType;
Result := True;
end;
Der Additionsoperator wird für einen String und eine komplexe Zahl implementiert (durch Umwandlung der komplexen Zahl in einen String und durch Verknüpfung). Die Operatoren für Addition, Subtraktion, Multiplikation und Division werden mithilfe der Methoden des TComplexData
-Objekts, das in den Daten des komplexen Variants gespeichert wird, für zwei komplexe Zahlen implementiert. Der Zugriff darauf erfolgt durch Umwandlung des TVarData
-Records in einen TComplexVarData
-Record und durch Benutzung des Elements VComplex
.
Alle anderen Operatoren oder Kombinationen von Typen führen zum Aufruf der Methode RaiseInvalidOp
, die einen Laufzeitfehler verursacht. Die Klasse TCustomVariantType
enthält neben RaiseInvalidOp
weitere nützliche Hilfsmethoden für die Implementierung von selbstdefinierten Variant-Typen.
BinaryOp
behandelt nur eine begrenzte Anzahl von Typen: Strings und andere komplexe Variants. Trotzdem ist es möglich, Operationen mit komplexen Zahlen und anderen numerischen Typen auszuführen. Dazu müssen die Operanden in komplexe Variants umgewandelt werden, bevor die Werte an BinaryOp
übergeben werden. Wie mit der Methode RightPromotion erzwungen werden kann, dass der rechte Operand ein komplexer Variant ist, wenn der linke Operand komplex ist, wurde bereits erläutert. Eine ähnliche Methode namens LeftPromotion erzwingt eine Umwandlung des linken Operanden, wenn der rechte komplex ist:
Delphi:
function TComplexVariantType.LeftPromotion(const V: TVarData; const Operator: TVarOp; out RequiredVarType: TVarType): Boolean;
begin
{ TypeX Op komplex }
if (Operator = opAdd) and VarDataIsStr(V) then
RequiredVarType := varString
else
RequiredVarType := VarType;
Result := True;
end;
Diese LeftPromotion
-Methode erzwingt die Umwandlung des linken Operanden in einen weiteren komplexen Variant. Sofern es sich beim linken Operanden allerdings um einen String und bei der Operation um eine Addition handelt, bleibt der Operand ein String.