Überladene Operatoren (Delphi)
Nach oben zu Klassen und Objekte - Index
Dieses Thema beschreibt Operatormethoden von Delphi und wie sie überladen werden.
Inhaltsverzeichnis
Allgemeines zum Überladen von Operatoren
Delphi ermöglicht es, bestimmte Funktionen, auch "Operatoren" genannt, innerhalb von Record-Deklarationen zu überladen. Der Name der Operatorfunktion wird dabei einem Symbol im Quelltext zugeordnet. Beispielsweise entspricht das Symbol + dem Operator Add.
Der Compiler vergleicht den jeweiligen Kontext (Rückgabetyp und Typ der im Aufruf verwendeten Parameter) mit der Signatur der Operatorfunktion, und ruft den entsprechenden überladenen Operator auf.
Die folgende Tabelle enthält die Delphi-Operatoren, die überladen werden können:
Operator | Kategorie | Deklarationssignatur | Symbolzuordnung |
---|---|---|---|
Implicit |
Konvertierung |
Implicit(a : Typ): Ergebnistyp; |
Implizite Typumwandlung |
Explicit |
Konvertierung |
Explicit(a: Typ): Ergebnistyp; |
Explizite Typumwandlung |
Negative |
Unär |
Negative(a: Typ): Ergebnistyp; |
- |
Positive |
Unär |
Positive(a: Typ): Ergebnistyp; |
+ |
Inc |
Unär |
Inc(a: Typ): Ergebnistyp; |
Inc |
Dec |
Unär |
Dec(a: Typ): Ergebnistyp |
Dec |
LogicalNot |
Unär |
LogicalNot(a: Typ): Ergebnistyp; |
not |
Trunc |
Unär |
Trunc(a: Typ): Ergebnistyp; |
Trunc |
Round |
Unär |
Round(a: Typ): Ergebnistyp; |
Round |
In |
Menge |
In(a: Typ; b: Typ): Boolean; |
in |
Equal |
Vergleich |
Equal(a: Typ; b: Typ): Boolean; |
= |
NotEqual |
Vergleich |
NotEqual(a: Typ; b: Typ): Boolean; |
<> |
GreaterThan |
Vergleich |
GreaterThan(a: Typ; b: type) Boolean; |
> |
GreaterThanOrEqual |
Vergleich |
GreaterThanOrEqual(a: Typ; b: Typ): Boolean; |
>= |
LessThan |
Vergleich |
LessThan(a: Typ; b: Typ): Boolean; |
< |
LessThanOrEqual |
Vergleich |
LessThanOrEqual(a: Typ; b: Typ): Boolean; |
<= |
Assign |
Binär |
Assign(var Dest: type; const [ref] Src: type); |
:= |
Add |
Binär |
Add(a: Typ; b: Typ): Ergebnistyp; |
+ |
Subtract |
Binär |
Subtract(a: Typ; b: Typ): Ergebnistyp; |
- |
Multiply |
Binär |
Multiply(a: Typ; b: Typ): Ergebnistyp; |
* |
Divide |
Binär |
Divide(a: Typ; b: Typ): Ergebnistyp; |
/ |
IntDivide |
Binär |
IntDivide(a: Typ; b: Typ): Ergebnistyp; |
div |
Modulus |
Binär |
Modulus(a: Typ; b: Typ): Ergebnistyp; |
mod |
LeftShift |
Binär |
LeftShift(a: Typ; b: Typ): Ergebnistyp; |
shl |
RightShift |
Binär |
RightShift(a: Typ; b: Typ): Ergebnistyp; |
shr |
LogicalAnd |
Binär |
LogicalAnd(a: Typ; b: Typ): Ergebnistyp; |
and |
LogicalOr |
Binär |
LogicalOr(a: Typ; b: Typ): Ergebnistyp; |
or |
LogicalXor |
Binär |
LogicalXor(a: Typ; b: Typ): Ergebnistyp; |
xor |
BitwiseAnd |
Binär |
BitwiseAnd(a: Typ; b: Typ): Ergebnistyp; |
and |
BitwiseOr |
Binär |
BitwiseOr(a: Typ; b: Typ): Ergebnistyp; |
or |
BitwiseXor |
Binär |
BitwiseXor(a: Typ; b: Typ): Ergebnistyp; |
xor |
Nur die in der Tabelle aufgeführten Operatoren können für einen Record definiert werden.
Es ist nicht möglich, eine überladene Operatormethode im Quelltext per Name zu referenzieren. Für den Zugriff auf eine bestimmte Operatormethode eines bestimmten Records siehe: Codebeispiel:OpOverloads_(Delphi). Operatorbezeichner sind für Records in der Sprache in der Methodenliste des Records aufgeführt und beginnen mit dem Wort "operator" (Beispiel: Methoden von System.AnsiStringBase). Sie können jeden der oben aufgeführten Operatoren in Ihre eigenen Records implementieren.
Der Compiler verwendet unter den folgenden Voraussetzungen einen Operator für einen Record:
- Bei Binäroperatoren muss ein Eingabeparameter der Record-Typ sein.
- Bei Unäroperatoren muss der Eingabeparameter oder der Rückgabewert der Record-Typ sein.
- Bei einem logischen Operator und einem bitweisen Operator mit demselben Symbol wird der logische Operator nur verwendet, wenn die Operanden boolesche Typen sind. Da der Typ des Records für diesen Record-Operator nicht boolesch ist, wird ein logischer Operator nur verwendet, wenn der andere Operand ein boolescher Typ ist.
Es bestehen keine Anforderungen bezüglich der distributiven oder kommutativen Eigenschaften der Operation. Bei binären Operatoren ist der erste Parameter immer der linke Operand und der zweite Parameter immer der rechte Operand. Sind keine Klammern vorhanden, erfolgt die Auswertung von links nach rechts.
Die Zuordnung von Operatormethoden erfolgt mittels der verfügbaren Operatoren der in der Operation verwendeten Typen (dies gilt auch für geerbte Operatoren). Wenn eine Operation mit den zwei unterschiedlichen Typen A und B für Typ A eine implizite Umwandlung in Typ B (und umgekehrt) vorsieht, ist keine Eindeutigkeit gegeben. Implizite Umwandlungen sollten nur - wenn unbedingt nötig - vorgenommen werden. Reflexivität ist zu vermeiden. Es ist am besten, eine implizite Umwandlung von Typ B in Typ A zu veranlassen und Typ A ohne Kenntnis von Typ B zu belassen (oder umgekehrt).
Grundsätzlich dürfen Operatoren ihre Operanden nicht verändern. Stattdessen muss ein neuer Wert zurückgegeben werden, der sich aus der Durchführung der Operation für die Parameter ergibt.
Überladene Operatoren werden meist in Records (Werttypen) verwendet.
- Hinweis: Unterstützende Records unterstützen das Überladen von Operatoren nicht.
Überladene Operatoren deklarieren
Überladene Operatoren werden in Records mit der folgenden Syntax deklariert:
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;
In der Implementierung überladener Operatoren muss auch die class operator-Syntax verwendet werden:
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;
Nachstehend finden Sie einige Beispiele für überladene Operatoren:
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;
Siehe auch
- Klassen und Objekte (Delphi)
- Felder (Delphi)
- Methoden (Delphi)
- Eigenschaften (Delphi)
- Verschachtelte Typdeklarationen
- Unterstützende Klassen und Records (Delphi)
- Klassenreferenzen
- Exceptions (Delphi)
- Codebeispiel: OpOverloads (Delphi)
- Codebeispiel: OpOverloads2 (Delphi)
- Methoden von System.AnsiStringBase