Vergleichsoperationen implementieren

Aus Appmethod Topics
Wechseln zu: Navigation, Suche

Nach oben zu Eine Klasse zur Aktivierung des selbstdefinierten Variant-Typs erzeugen


Es gibt zwei Möglichkeiten, einem selbstdefinierten Variant-Typ Vergleichsoperationen (=, <>, <, <=, >, >=) zu ermöglichen. Sie können entweder die Methode Compare oder die Methode CompareOp überschreiben.

Die Methode Compare ist einfacher, wenn Ihr selbstdefinierter Variant-Typ sämtliche Vergleichsoperatoren unterstützt. Diese Methode nimmt drei Parameter entgegen: den linken und rechten Operanden sowie einen var-Parameter, der das Vergleichsergebnis zurückgibt.

Das Objekt TConvertVariantType aus der Unit VarConv implementiert z.B. die folgende Compare-Methode:

Object Pascal:

 procedure TConvertVariantType.Compare(const Left, Right: TVarData;
 var Relationship: TVarCompareResult);
 const
 CRelationshipToRelationship: array [TValueRelationship] of TVarCompareResult =
 (crLessThan, crEqual, crGreaterThan);
 var
 LValue: Double;
 LType: TConvType;
 LRelationship: TValueRelationship;
 begin
 // unterstützt...
 //   convvar cmp zahl
 //     Vergleicht den Wert von convvar und zahl
   //   convvar1 cmp convvar2
 //     Vergleich nach Umwandlung von convvar2 in den Unit-Typ von convvar1
   //  Der rechte Operand kann auch ein String sein.  Enthält der String Unit-Informationen,
 //    wird er wie eine varConvert behandelt, sonst wie ein Double.
 LRelationship := EqualsValue;
 case Right.VType of
     varString:
       if TryStrToConvUnit(Variant(Right), LValue, LType) then
         if LType = CIllegalConvType then
           LRelationship := CompareValue(TConvertVarData(Left).VValue, LValue)
         else
           LRelationship := ConvUnitCompareValue(TConvertVarData(Left).VValue,
                                              TConvertVarData(Left).VConvType, LValue, LType)
         else
           RaiseCastError;
     varDouble:
       LRelationship := CompareValue(TConvertVarData(Left).VValue, TVarData(Right).VDouble);
     else
       if Left.VType = VarType then
         LRelationship := ConvUnitCompareValue(TConvertVarData(Left).VValue,
                            TConvertVarData(Left).VConvType, TConvertVarData(Right).VValue,
                            TConvertVarData(Right).VConvType)
       else
         RaiseInvalidOp;
   end;
   Relationship := CRelationshipToRelationship[LRelationship];
 end;

Unterstützt der selbstdefinierte Typ nicht die Vergleichsarten "größer als" oder "kleiner als", sondern nur "gleich" und "ungleich", ist es schwierig, die Methode Compare zu implementieren, weil sie crLessThan, crEqual oder crGreaterThan zurückgeben muss. Bei "ungleich" als einzig möglicher Antwort ist jedoch nicht zu bestimmen, ob crLessThan oder crGreaterThan als Rückgabewert in Frage kommt.

In diesem Fall muss statt der Methode Compare die Methode CompareOp überschrieben werden.

CompareOp besitzt drei Parameter: den Wert des linken Operanden, den Wert des rechten Operanden sowie den Vergleichsoperator. Implementieren Sie diese Methode zur Ausführung der Operation und geben Sie einen Booleschen Wert zurück, wenn der Vergleich True ergibt. Ergibt der Vergleich keinen Sinn, rufen Sie anschließend die Methode RaiseInvalidOp auf.

Die folgende CompareOp-Methode entstammt z.B. dem TComplexVariantType-Objekt aus der Unit System.VarCmplx. Sie unterstützt nur die Prüfung auf Gleichheit oder Ungleichheit.

Object Pascal:

 function TComplexVariantType.CompareOp(const Left, Right: TVarData;
 const Operator: Integer): Boolean;
 begin
   Result := False;
 if (Left.VType = VarType) and (Right.VType = VarType) then
     case Operator of
       opCmpEQ:
         Result := TComplexVarData(Left).VComplex.Equal(TComplexVarData(Right).VComplex);
       opCmpNE:
         Result := not TComplexVarData(Left).VComplex.Equal(TComplexVarData(Right).VComplex);
     else
       RaiseInvalidOp;
     end
 else
   RaiseInvalidOp;
 end;

Beachten Sie, dass diese beiden Implementierungen nur eine sehr begrenzte Anzahl von Typen als Operanden unterstützen. Wie bei binären Operationen können Sie auch hier die Methoden RightPromotion und LeftPromotion verwenden, um die Anzahl der zu berücksichtigenden Fälle zu beschränken, indem Sie eine Umwandlung erzwingen, bevor Compare oder CompareOp aufgerufen wird.

Siehe auch