Generics
関数の Generics
関数名の直後に <T> を記述することで、型パラメータを定義できます。
fn func<T>( val:T ): List<T> {
return [ val ];
}
let l1 = func( 10 ); // List
let l2 = func( "abc" ); // List
呼び出し時の型推論が効くため、
func<int>(10) のように明示する必要は通常ありません。
クラスの Generics
クラス名の直後に <T> を記述します。
class Box<T> {
let val:T;
pub fn __init( val:T ) { self.val = val; }
pub fn get(): T { return self.val; }
}
let b = new Box( 100 ); // Box
※ インタフェースは Generics をサポートしていません。
型パラメータの制約
<T:Constraint> の形式で、型パラメータが特定のクラスを継承、またはインタフェースを実装していることを強制できます。
interface Val {
pub fn getValue(): int;
}
fn printVal<T:(Val)>( obj:T ) {
print( obj.getValue() ); // T は Val を実装しているので呼び出し可能
}
Mapping 可能な Generics クラスを作る場合にも制約が必須となります。
class Model<T:(Mapping)> extend (Mapping) {
let data:T;
}
上記の T:(Mapping) がないと、Mapping インタフェースの実装要件 (全メンバが Mapping 可能であること) を満たせない可能性があるためコンパイルエラーとなります。
メソッドの Generics
クラスのメソッド個別に型パラメータを持たせることも可能です。
class Test {
pub fn convert<T>( val:T ): str {
return "val: %s" (val);
}
}
Generics と Mutability
型パラメータ T は、宣言時に修飾することで Mutability や Nilability を制御できます。
fn func<T>( val:T ): &T { return val; } // Immutable な T を返す
fn func2<T>( val:T! ): T { return unwrap val; } // Nilable な引数を受け取り、Non-nil を返す
<T!> のように、型パラメータの定義自体に ! を付けることはできません。func<T>( val:T! ) のように使用箇所で指定します。