As in C++, operators in moto can be overloaded giving moto programmers concise semantics for expressing common operations on objects. When an operator for a class is overloaded moto programmers can write code using operators that expands behind the scenes to function and method calls. For example the moto code A[0]=B+C may be used as short hand for A.setAt(0,union(B,C)) depending on the types of the variables A,B, and C.
The String class is an example of a moto class that makes use of operator overloading. String addition with the + and += operators, or String comparison with the eq, ne, lt, gt, lte, and gte operators is not built in to the moto language. Rather it is implemented through the use of overloaded operators.
The moto utility classes (from the moto.util) extension make the widest use of this facility. You can set and retrieve objects from vectors and hashes using array notation. You can union or intersect sets using the + and * operators. You can even compare the contents of most any two objects of the same type with the 'eq' and 'ne' operators.
A primary use of overloaded operators is to make commonly performed operations on commonly used objects appear 'first class' in the language.
This is the case with Vectors and Symboltables (hashes). This is due to their relation to Arrays.
Arrays are a first class feature of most all programming languages. Thus they are operated on by operators. Specifically, the [] and []= operators are used to set and get elements in an array.
$do(my_array[13] = "foo")
$return(my_array[27])
| |
Vectors (from the codex.util extension) are just like arrays except they are not bounded and can grow as new objects are added to them. In both Java and Moto a Vector's contents can be set and retrieved through methods:
$do(my_vector.set(13,"foo"))
$return(my_vector.get(27))
| |
However since a Vector is so much like an Array it makes sense that it should be accessible with the same concise operator syntax. Because of operator overloading, in Moto you can treat a Vector like an array using the very same syntax:
$do(my_vector[13] = "foo")
$return(my_vector[27])
| |
SymbolTables are also a lot like arrays except they are unbounded and have keys that are Strings. But since they are so much like arrays it once again makes sense that programmers should be able to access them with the same semantics:
$do(my_symboltable["foo"] = "bar")
$return(my_symboltable["maka"])
| |
You can find out what operations are overloaded for a particular class by looking at the class's interface. In the 'Method operators' and 'Related Functions operators' sections you will find all the overloaded operators for class:
StringSet
|
Method operators |
StringSet StringSet::+=(StringSet i)
Returns the union of two StringSets |
StringSet StringSet::*=(StringSet i)
Returns the intersection of StringSet i1 and StringSet i2 |
StringSet StringSet::-=(StringSet i)
Returns the difference StringSet i1 and StringSet i2 |
Related Functions operators |
StringSet +(StringSet s1,StringSet s2)
Returns the union of two StringSets - {x:x is in s1 or x is in s2 } |
StringSet *(StringSet s1,StringSet s2)
Returns the intersection of two StringSets - {x:x is in s1 and x is in s2 } |
StringSet -(StringSet s1,StringSet s2)
Returns the difference StringSet i1 and StringSet i2 - {x:x is in s1, x is not in s2} |
|
What the above interface is saying is that there are six overloaded operations having to do with StringSets. The + and += operations have been overloaded to mean set union when applied to StringSets. The * and *= operations have been overloaded to mean set intersection . The - and -= operations have been overloaded to mean set difference .
There is a difference between an between an Object having the same content (or contents) as another object, and two variables referring to the same object.
If one were to create two vectors and add the String "foo" to both of them they would be equal in the sense that they are both vectors of size 1 with the String "foo" inside of them.
Vector v1 = new Vector();
Vector v2 = new Vector();
v1.add("foo");
v2.add("foo");
print v1 eq v2; // outputs true
print v1 == v2; // outputs false
| |
However vectors v1 and v2 in the above example are not the same object. They have seperate storage in memory and can be altered independantly of one another. If however we re-wrote the above example as
Vector v1 = new Vector();
Vector v2 = v1;
v1.add("foo");
v2.add("foo");
print v1 eq v2; // outputs true
print v1 == v2; // outputs true
print v1.toString() // outputs {"foo","foo"}
| |
Then v1 and v2 would be reffering to the same object. In this example only one object was ever created. Adding "foo" to v1 and then adding "foo" to v2 added two "foo"s to the same Vector!
This is the difference exposed by the == and eq operators. The eq operator will output true if two objects are equal, the == operator will output true if its operands are two references to the same object.
For this reason the == and != operators are never overloaded since there meaning is already well defined for all classes of objects. However the eq operator is overloaded for most every type of object and can be used to tell if the contents of two objects are equal.
Copyright © 2000 - 2003 David Hakim