Gosu supports Java-style Generics, but the rules are slightly different:
You use generics just like you do in Java:
var lst = new java.util.List<String>() lst.add("A String") for( s in lst ) { print( '"${s}" has length ${s.length}') }Everything is statically typed and, thus, can support code completion.
When I say type parameters are covariant, what I mean is that this code works:
var lst = new java.util.List<String>() lst.add("A String") var lstOfObjs : List<Object> = lst // This assignment is allowed, since String is assignable to ObjectTechnically, this is unsound, because you could do this:
lstOfObjs.add( 11 ) // oopsHowever, this is not a common error, as evidenced by the fact that Java was able to be a perfectly productive programming language for many years with untyped collections, and by the fact that so many people are productive in dynamically typed languages.
An advantage of this approach to Generics is that Gosu can have a properly typed List.contains()
method
as well:
var lst = new java.util.List<String>() lst.contains( 10 ) // compilation error in Gosu, unlike Java and ScalaIt turns out that (as of this writing) both Java and Scala can't properly type
contains()
due to their generics systems.
Covariant Generics will not please people who enjoy type theory or who feel that a type system is there to catch every possible error, but, in our experience, this approach gives you the biggest bang for your buck when writing practical software.
You declare type variables just like you do in Java:
package example class MyGenericClass<T> { var _tee : T as readonly Tee construct( tee : T ) { _tee = tee } }
You can constrain type variables just like you do in Java:
package example class MyGenericClass<T extends Runnable> { var _tee : T as readonly Tee construct( tee : T ) { _tee = tee } }
You can refer to type variables as expressions:
package example uses gw.lang.reflect.IType class MyGenericClass<T> { var _tee : T as readonly Tee construct( tee : T ) { _tee = tee } property get TeeType : IType { return T } }
You can also declare generic functions:
package example class MyGenericClass<T> { var _tee : T as readonly Tee construct( tee : T ) { _tee = tee } static function create<T2>( val : T2 ) : MyGenericClass<T2> { return new MyGenericClass<T2>( val ) } }which are invoked as you would expect:
var x = MyGenericClass.create<String>("A String")Of course, you can just let type inference do its thing as well:
var x = MyGenericClass.create("A String") // Still typed as MyGenericClass<String> thanks to type inference