О перегрузке операторов
Delphi для Win32 разрешает перегрузку некоторых функций или "операторов" внутри объявления записей. Имя функции оператора сопоставляется в программном коде с его символьным представлением. Например, оператор Add сопоставляется с символом + . Компилятор генерирует вызов соответствующего перегружаемого оператора, сопоставляя контекст (то есть возвращаемый тип и тип параметров, использованных при вызове) с сигнатурой функции оператора.
Следующая таблица показывает операторы языка Delphi, которые могут быть перегружены:
Оператор | Категория | Сигнатура объявления | Совмещаемый символ |
---|---|---|---|
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; | <= |
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 |
Операторы, не перечисленные в этой таблице, не могут быть использованы для работы с классами или записями. Методы перегруженных операторов не могут вызываться по имени в программном коде. Для доступа к методу оператора в определенном классе или записи см. Code Example:OpOverloads_(Delphi). Идентификаторы операторов, включенные в список элементов класса или записи, начинаются с ключевого слова "operator" (пример:System.AnsiStringBase_Functions). Вы можете реализовать любой из вышеперечисленных операторов в собственных классах и записях.
Компилятор будет использовать для класса или записи оператор в том случае если:
- Для бинарных операторов: один из входных параметров должен быть классом;
- Для унарных операторов классом должен быть либо входной параметр, либо возвращаемое значение;
- Для логического оператора и побитового оператора, использующих один и тот же символ, логический оператор используется только когда операнды относятся к булевскому типу. Если тип класса этого оператора класса не является булевским, логический оператор будет использован только если другой операнд является булевским.
Для распределительных или коммутативных свойств операции не делается предположений. Для бинарных операторов первым параметром является всегда левый операнд, а правый – вторым. Предполагается ассоциативность в порядке слева-направо при отсутствии явно указанных скобок.
Разрешение методов операторов выполняется через объединение доступных операторов для типов, использованных в операции (включая наследуемые операторы). Для операции, включающей два различных типа A и B: если тип A может быть неявно преобразован к В, а В может быть неявно преобразован к А, будет иметь место неоднозначная интерпретация. Неявные преобразования должны использоваться только там, где они абсолютно необходимы, а рефлексивность должна быть исключена. Наилучшим решением будет разрешить типу В неявно преобразовать себя в тип А, позволив типу А ничего не знать о типе В (или наоборот).
Основным правилом является то, что операторы не должны изменять операнды, а возвращать новое значение, созданное при работе с параметрами.
Перегружаемые операторы особенно часто используются в записях (то есть в значимых типах).
Объявление перегрузки операторов
Перегрузка операторов объявляется внутри классов или записей со следующим синтаксисом:
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 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;// Добавление двух операндов типа TMyRecord class operator Subtract(a, b: TMyRecord): TMyRecord;// Вычитание типов TMyRecord class operator Implicit(a: Integer): TMyRecord;// Неявное преобразование Integer к TMyRecord class operator Implicit(a: TMyRecord): Integer;// Неявное преобразование TMyRecord к Integer class operator Explicit(a: Double): TMyRecord;// Явное преобразование Double к TMyRecord end; // Пример реализации Add class operator TMyRecord.Add(a, b: TMyRecord): TMyRecord; begin // ... end; var x, y: TMyRecord; begin x := 12; // Неявное преобразование к Integer y := x + x; // ВызовTMyRecord.Add(a, b: TMyRecord): TMyRecord b := b + 100; // Вызов TMyRecord.Add(b, TMyRecord.Implicit(100)) end;
Спасибо, а внутри класса можно как-нибудь реализовать это?
ОтветитьУдалитьЯ то думаю чего вы ссылку не даете на embarcaderoвский мануал, а вы с него примеры с катали. Очень глупо, но хотелось бы чтобы вы опомнились и свои рабочие и наглядные примеры написали.
ОтветитьУдалитьx := 12; // Неявное преобразование к Integer
ОтветитьУдалитьЗдесь ошибка перевода хелпа
x := 12; // Implicit conversion from an Integer
Преобразование из Integer