Génériques
Les génériques permettent de paramétrer un type basé sur un autre type. Considérons un type Box:
class MyBox(T)
def initialize(@value : T)
end
def value
@value
end
end
int_box = MyBox(Int32).new(1)
int_box.value # => 1 (Int32)
string_box = MyBox(String).new("hello")
string_box.value # => "hello" (String)
another_box = MyBox(String).new(1) # Error, Int32 doesn't match String
Les Génériques sont particulièrement utiles pour implémenter des types de collection. Array, Hash, Set sont des types génériques. Pointer également.
Plus d'un argument de type est permis:
class MyDictionary(K, V)
end
Seules des noms d'un unique caractère sont autorisés comme noms d'arguments de type.
Inférence de variables de type
Les restrictions de type dans un constructeur de type générique sont des variables libres quand les arguments de type ne sont pas spécifiés, et sont ensuite utilisés pour l'inférence. Par exemple:
MyBox.new(1) # : MyBox(Int32)
MyBox.new("hello") # : MyBox(String)
Dans le code précédent nous n'avons pas spécifié les arguments de type de MyBox,
le compilateur les a déduits d'après la logique suivante:
MyBox.new(value)délégue àinitialize(@value : T),Tn'existe pas, il est donc utilisé comme variable libre,- Parce-que
MyBoxest en faitMyBox(T), etTest à la fois une variable libre et un argument de type,Tdevient le type de la valeur passée en paramètre.
De cette manière il est moins laborieux de travailler avec les génériques.
Structs et modules génériques
Structs et modules peuvent être génériques également. Quand un module est générique vous l'incluez de cette manière:
module Moo(T)
def t
T
end
end
class Foo(U)
include Moo(U)
def initialize(@value : U)
end
end
foo = Foo.new(1)
foo.t # Int32
Notez que dans l'exmple précédent T devient Int32 car Foo.new(1) transforme U en Int32, qui à son tour transforme T en Int32 via l'inclusion du module générique.
Héritage de types génériques
Les classes et structs génériques peuvent être hérités. Lors de l'héritage vous pouvez spécifier une instance du type générique, ou déléguer les variables de type:
class Parent(T)
end
class Int32Child < Parent(Int32)
end
class GenericChild(T) < Parent(T)
end