二項演算の実装
クラスを作成してカスタム バリアント型を有効にする への移動
カスタム バリアント型が、標準の二項演算子(System ユニットにリストされている +、-、*、/、div、mod、shl、shr、and、or、xor)と動作するようにするには、BinaryOp メソッドをオーバーライドしなければなりません。 BinaryOp
には 3 つのパラメータ --- 左側オペランドの値、右側オペランドの値、および演算子 --- があります。 演算を実行するためにこのメソッドを実装し、左側オペランドを格納していた同じ変数を使用して、結果を返します。
BinaryOp
たとえば、次の BinaryOp メソッドは、System.VarCmplx ユニットで定義される TComplexVariantType
からきています。
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;
この実装では、いくつか注意すべき点があります:
このメソッドは、演算子の右側にあるバリアントが、複素数を表すカスタム バリアントである場合にのみ、処理を行います。 もし左側オペランドが複素数バリアントで、右側オペランドがそうでない場合、複素数バリアントはまず、右側オペランドを複素数バリアントに強制キャストします。 これは、RightPromotion メソッドをオーバーライドし、常に VarType
プロパティに型を要求するようにすることで行われます:
Delphi:
function TComplexVariantType.RightPromotion(const V: TVarData;
const Operator: TVarOp; out RequiredVarType: TVarType): Boolean;
begin
{ Complex Op TypeX }
RequiredVarType := VarType;
Result := True;
end;
加算演算子は、文字列と複素数に対して実装されており(複素数値を文字列にキャストし連結する)、また、加算、減算、乗算、除算の各演算子は、2 つの複素数に対しても実装されており、その際には、複素数バリアントのデータに格納される TComplexData
オブジェクトの各メソッドを使用します。 これは、TVarData
レコードを TComplexVarData
レコードにキャストし、その VComplex
メンバーを使用することにより、アクセスすることができます。
RaiseInvalidOp
メソッドを呼び出し、ランタイム エラーが発生します。 TCustomVariantType
クラスは、数多くのユーティリティ メソッド(RaiseInvalidOp
など)を保有しており、カスタム バリアント型の実装から使用することができます。BinaryOp
は、限られた数の型 --- 文字列、および、その他の複素数バリアント -- しか処理しません。 しかし、複素数と他の数値型との間で、演算を実行することは可能です。 BinaryOp
メソッドを機能させるには、値をこのメソッドに渡す前に、オペランドを複素数バリアントにキャストしなければなりません。 左側オペランドが複素数の場合、RightPromotion
メソッドを使用して、右側オペランドを強制的に複素数バリアントにする方法については、すでに見てきました。 同様のメソッド、LeftPromotion が、右側オペランドが複素数の場合に、左側オペランドを強制的にキャストします。
function TComplexVariantType.LeftPromotion(const V: TVarData; const Operator: TVarOp; out RequiredVarType: TVarType): Boolean;
begin
{ TypeX Op Complex }
if (Operator = opAdd) and VarDataIsStr(V) then
RequiredVarType := varString
else
RequiredVarType := VarType;
Result := True;
end;
この LeftPromotion
メソッドは、左側オペランドを別の複素数バリアントに強制的にキャストします。ただし、左側オペランドが文字列で、演算が加算の場合は、LeftPromotion
はオペランドを文字列のままにします。