A generic prototype in Cyan takes a type (or a generic symbol) as a parameter just like generic classes in Java or template classes in C++:
object Box<T> func init: T value { self.value = value } func mult: T other -> T = self.value * other; // create get and set methods @property var T value end
For each new parameter, a new Box
prototype is created (like in C++ and unlike in Java). Therefore, Box<Int>
and Box<Float>
and two unrelated prototypes.
In method mult:
of Box
, there is the sending of message *
with argument other
to field value
of type T
. That means that T
should have a method
func * (T other) -> T
in order to compile correctly.
If the supplied type T
in the instantiation, like Box
, does not have this method, there is a compilation error:
// String does not define a * method var Box<String> bs;
The error issued is:
The type of the real argument, 'cyan.lang.String', of expression 'other' is not sub-prototype of the type of the formal parameter, 'cyan.lang.Int' in message send with keyword '*' Stack of generic prototype instantiations: main.Box<String> line 8 column 45 main.Program line 11 column 17 func mult: (String other) -> String = self.value * other;
The compiler shows code Box<String>
in the error message, which is confusing. A better option is to use metaobject concept
:
@concept{* T has [ func * T -> T ] *} object Box<T> func init: T value { self.value = value } func mult: T other -> T = self.value * other; // create get and set methods @property var T value end
Now, the error message is clearer:
A concept associated to generic prototype 'main.Box<String>' expected that method '* String -> String' were in prototype 'cyan.lang.String' Stack of generic prototype instantiations: main.Program line 11 column 17 var b = Box<String>("");