一、关于记录操作重载
Delphi 允许在记录声明中重载某些函数或 "操作符"。操作符函数的名称映射到源代码中的符号表示。例如,Add 运算符映射到 + 符号。
编译器会根据操作符函数的名称,生成对相应重载的调用,并匹配上下文(即返回类型和调用中使用的参数类型)。
下表列出了可以重载的 Delphi 运算符:
Operator | Category | Declaration Signature | Symbol Mapping |
---|---|---|---|
Implicit | Conversion | Implicit(a : type) : resultType; | implicit typecast |
Explicit | Conversion | Explicit(a: type) : resultType; | explicit typecast |
Negative | Unary | Negative(a: type) : resultType; | - |
Positive | Unary | Positive(a: type): resultType; | + |
Inc | Unary | Inc(a: type) : resultType; | Inc |
Dec | Unary | Dec(a: type): resultType | Dec |
LogicalNot | Unary | LogicalNot(a: type): resultType; | not |
Trunc | Unary | Trunc(a: type): resultType; | Trunc |
Round | Unary | Round(a: type): resultType; | Round |
In | Set | In(a: type; b: type) : Boolean; | in |
Equal | Comparison | Equal(a: type; b: type) : Boolean; | = |
NotEqual | Comparison | NotEqual(a: type; b: type): Boolean; | <> |
GreaterThan | Comparison | GreaterThan(a: type; b: type) Boolean; | > |
GreaterThanOrEqual | Comparison | GreaterThanOrEqual(a: type; b: type): Boolean; | >= |
LessThan | Comparison | LessThan(a: type; b: type): Boolean; | < |
LessThanOrEqual | Comparison | LessThanOrEqual(a: type; b: type): Boolean; | <= |
Assign | Binary | Assign(var Dest: type; const [ref] Src: type); | := |
Add | Binary | Add(a: type; b: type): resultType; | + |
Subtract | Binary | Subtract(a: type; b: type) : resultType; | - |
Multiply | Binary | Multiply(a: type; b: type) : resultType; | * |
Divide | Binary | Divide(a: type; b: type) : resultType; | / |
IntDivide | Binary | IntDivide(a: type; b: type): resultType; | div |
Modulus | Binary | Modulus(a: type; b: type): resultType; | mod |
LeftShift | Binary | LeftShift(a: type; b: type): resultType; | shl |
RightShift | Binary | RightShift(a: type; b: type): resultType; | shr |
LogicalAnd | Binary | LogicalAnd(a: type; b: type): resultType; | and |
LogicalOr | Binary | LogicalOr(a: type; b: type): resultType; | or |
LogicalXor | Binary | LogicalXor(a: type; b: type): resultType; | xor |
BitwiseAnd | Binary | BitwiseAnd(a: type; b: type): resultType; | and |
BitwiseOr | Binary | BitwiseOr(a: type; b: type): resultType; | or |
BitwiseXor | Binary | BitwiseXor(a: type; b: type): resultType; | xor |
除表中列出的操作符外,记录中不得定义其他操作符。
重载的操作符方法不能在源代码中通过名称引用。要访问特定记录的特定操作符方法,请参阅 下面示例)。运算符标识符包含在以 "运算符 "开头的语言记录方法列表中(例如:System.AnsiStringBase 方法)。您可以在自己的记录中实现上述任何操作符。
只要符合以下条件,编译器就会为记录使用运算符:
- 对于二元运算符,其中一个输入参数必须是记录类型。
- 对于一元运算符,输入参数或返回值必须是记录类型。
- 对于使用相同符号的逻辑运算符和位运算符,逻辑运算符仅在操作数为布尔时使用。由于此记录运算符的记录类型不是布尔型,因此只有当另一个操作数是布尔型时,才会使用逻辑运算符。
不对运算的分配或交换性质做任何假设。对于二元运算符,第一个参数总是左操作数,第二个参数总是右操作数。在没有明确括号的情况下,关联性被假定为从左到右。
操作符方法的解析是在操作中使用的类型的可访问操作符的联合体上完成的(注意这包括继承操作符)。对于涉及两个不同类型 A 和 B 的操作,如果 A 类型隐式转换为 B 类型,而 B 类型隐式转换为 A 类型,就会产生歧义。只有在绝对必要的情况下才提供隐式转换,并应避免反向性。最好让 B 类型隐式地转换为 A 类型,而让 A 类型不知道 B 类型(反之亦然)。
一般来说,操作符不应修改其操作数。相反,应通过对参数执行操作来返回一个新值。
重载操作符最常用于记录(即值类型)。
注意:记录助手(Record helpers)不支持操作符重载。
二、声明操作符重载
操作符重载在记录中声明,语法如下:
type
typeName = record
class operator conversionOp(a: type): resultType;
class operator unaryOp(a: type): resultType;
class operator comparisonOp(a: type; b: type): Boolean;
class operator binaryOp(a: type; b: type): resultType;
end;
重载操作符的实现也必须包含类操作符(class operator)语法:
class operator typeName.conversionOp(a: type): resultType;
class operator typeName.unaryOp(a: type): resultType;
class operator typeName.comparisonOp(a: type; b: type): Boolean;
class operator typeName.binaryOp(a: type; b: type): resultType;
下面是一些重载操作符的示例:
type
TMyRecord = record
class operator Add(a, b: TMyRecord): TMyRecord; // Addition of two operands of type TMyRecord
class operator Subtract(a, b: TMyRecord): TMyRecord; // Subtraction of type TMyRecord
class operator Implicit(a: Integer): TMyRecord; // Implicit conversion of an Integer to type TMyRecord
class operator Implicit(a: TMyRecord): Integer; // Implicit conversion of TMyRecordto Integer
class operator Explicit(a: Double): TMyRecord; // Explicit conversion of a Double to TMyRecord
end;
// Example implementation of Add
class operator TMyRecord.Add(a, b: TMyRecord): TMyRecord;
begin
// ...
end;
var
x, y: TMyRecord;
begin
x := 12; // Implicit conversion from an Integer
y := x + x; // Calls TMyRecord.Add(a, b: TMyRecord): TMyRecord
b := b + 100; // Calls TMyRecord.Add(b, TMyRecord.Implicit(100))
end;
再举一个示例:
TPassphrase = record
private
FType: TPassphraseType;
FValue: TBytes;
FKey: TBytes;
FInitVector: TBytes;
public
class operator Implicit(const Value: string): TPassphrase;
class operator Implicit(const Value: TBytes): TPassphrase;
constructor Create(const Key, InitVector: TBytes); overload;
constructor Create(const Password: string; Encoding: TEncoding); overload;
end;
{ TPassphrase }
class operator TPassphrase.Implicit(const Value: string): TPassphrase;
begin
Result.FType := ptPassword;
Result.FValue := TEncoding.UTF8.GetBytes(Value);
end;
class operator TPassphrase.Implicit(const Value: TBytes): TPassphrase;
begin
Result.FType := ptPassword;
Result.FValue := Value;
end;
constructor TPassphrase.Create(const Key, InitVector: TBytes);
begin
FType := ptKeys;
FKey := Key;
FInitVector := InitVector;
end;
constructor TPassphrase.Create(const Password: string; Encoding: TEncoding);
begin
FType := ptPassword;
FValue := Encoding.GetBytes(Password);
end;
使用如下:
var
Password: TBytes
FCipher.Passphrase:=Password;
//以上调用 class operator Implicit(const Value: TBytes): TPassphrase;