Binäre Operationen implementieren

Aus Appmethod Topics
Wechseln zu: Navigation, Suche

Nach oben zu RTL verwenden - Index

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):

Object Pascal:

 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.

Object Pascal:

 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:

Object Pascal:

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.

Siehe auch