Custom Operators

Types provide custom operarors implementations to override the behavior of many of the standard Unary and Binary Operartor Expressions for specific type combinations.

Foer example, if a class or record contains data that, logically, a + operation would make sense for, a custom Add operator can be provided to allow the expression a + b to evaluated using the correct rules.

Note: Custom Operators (like Constructors and Finalizers ) are very similar in structure to regular methods, and many topics covered in the Methods topic will apply to them, as well.

This includes the sections on Parameters, Result, Method Body and Pre- and Post-Conditions.

Operators can be defined for Classes and Records, as well as for other types (including external ones) via Extensions or as Globals)

The following standard operators can be overridden: +, -, *, /, div, mod, and, or, xor, <, , =, >, and . In addition, two cast operators, Implicit and Explicit, can be provided to allow implicit and explicit casting from and to other types.

A custom operator declaration consists of the operator keyword and the operator name, always followed by a list of parameters in parenthesis, and a result type. The names and list of parameters are well-defined and must match the table below.

Operators are always considered static; the static Member Modifier or a class keyword prefix are optional for consistency, and have no effect.

type
  ComplexNumber = public record
  public
    Real: Double;
    Imagnary: Double;

    operator Add(lhs: ComplexNumber, rhs: ComplexNumber): ComplexNumber;
    
    operator Implict(aOther: Double): ComplexNumber;
    operator Explicit(aOther: Double): ComplexNumber;
    operator Explicit(aOther: ComplexNumber): Double;
  end;

At least one parameter (or, for casts, the result) must be of the type that the operator is defined on. The other parameter can be of a different type:

operator Add(lhs: ComplexNumber, rhs: Double): ComplexNumber;
operator Add(lhs: Double, rhs: ComplexNumber): ComplexNumber;

Using Operators

Expressions using the above operators will automatically use custom operators, the right and left hand side of the expression (or just the single operand, for Unary Operartors such as not) are strongly typed to match the parameters of an operator (or one of the vase classes).

For example, an Add operator defined such as

type 
  Foo = class
    operator Add(aFoo: Foo; aOther: Object);

would be called for any expression such as a + b where a is of type Foo, and b is any type (that descends from Object).

Note that the operands need to be strongly types, as operator overloading is resolved at comile time. For example, in the following scenario, the custom operator would not be called, even though a holds a Foo class at runtime, because to the compiler, a is just an object, and operarors are not Polymorphic:

var a: Object := new Foo();
var b: Object := "Hello"
var x := a+b;

Operators can be kept "flexible" by keeping one parameter weekly-typed (such as in the example above), and checking for the best operation at runtime, in the operator's implementation. For example, the above operator allows to add a Foo instance to just about anything else – bei it a String, an Integer, or even anotherFoo. It is then up to implementation to take the appropriate action depending on the type of aOther.

Operator Names

The following special names need to be used when implementing operators:

Name Oxygene Operator Comments
Plus + Unary, +5
Minus - Unary, -5
BitwiseNot not Bitwise not
not Logical not (not supported)
   
Increment ++ (not callable from Oxygene)
Decrement -- (not callable from Oxygene)
Implicit Implicit
Explicit Explicit Manual type casts with as or ()
True True  
False False  
Add + "5+3"
Subtract - "5-3"
Multiply * "5*3"
Divide /, div "5/3"
Modulus mod "5 mod 3"
BitwiseAnd and Bitwise "and"
BitwiseOr or Bitwise "or"
BitwiseXor xor Bitwise "xor"
ShiftLft shl  
ShiftRight shr  
Equal =  
NotEqual , <>  
Less <  
LessOrEqual , <=  
Greater >,  
GreaterOrEqual , >=  
In in Sets
and Logical (not supported)
or Logical (not supported)
xor Logical (not supported)

Visibility

The visibility of operators is governed by the Visibility Section of the containing type the operator is declared in, or the Visibility Modifiers applied to the operator.

Static/Class Constants

Operators are always static and do not have access to instance data (except of course the instances passed in as parameters). They do not need to (but are allowed to) be prefixed with the class keyword or have a static Member Modifier.

Virtuality

Since operators are always static, they do not participate in Polymorphism, and cannot have Virtuality Modifiers.

Other Modifiers

A number of other Member Modifiers can be applied to operators.

See Also