総称型 / ジェネリクス 2014/10/27
値の型として、例えば単なる「リスト」ではなく、「整数のリスト」や、「文字列のリストのリスト」など、要素の型も指定できるような機能。要素の型の部分を型パラメータと言ったりする。
C++ 2014/10/27
クラステンプレートや関数テンプレートの機能があるが、詳細はもう忘れた。
型パラメータの表記はJavaと似ていて、<...>
を使う。
Java 2015/02/19
Genericsとか総称型とも言ったりする。
「整数のリスト」は List<Integer>
のように書く。
Java7からは <...>
の内側を省略できる場合もあり、中身が省略された <>
をダイアモンド演算子という。
インスタンス生成の例
Map<String, List<Integer>> map = new HashMap<>();
クラス定義の例
public class FooClass<A, B> extends SuperClass {
...
}
メソッド定義の例
public <A, B> B bar(A a) {
...
}
Scala 2014/10/27
Javaでは型パラメータを囲むのに <>
を使っているが、
Scalaでは []
を使う。
例
val map: Map[String, List[Int]] = Map.empty;
クラス定義でのジェネリクス
Java 2014/10/27
例
public class Foo<T1, T2> {
...
}
Scala 2014/10/27
例
class Foo[T1, T2] {
...
}
メソッド定義でのジェネリクス 2014/10/27
クラス定義に存在する型パラメータはそのままメソッド定義でも使える。
クラス定義に存在する型パラメータをメソッド単位で新たに導入したい場合には、メソッド定義で型パラメータを宣言する。
Java 2014/10/27
例
public <T1, T2> T1 bar(T2: arg) {
...;
}
Scala 2014/10/27
例
def bar[T1, T2](T2: arg): T1 = {
...;
}
型パラメータの制約の宣言 2014/10/27
型パラメータに当てはまる型を、特定の型またはそれを継承する型(子クラス、孫クラス、、、)に限定したい場合に、それを上限境界という。
逆に、型パラメータに当てはまる型を、特定の型またはそれの親となる型(親クラス、祖父母クラス、、、)に限定したい場合に、それを下限境界という。
Scalaではさらに、ダックタイピングみたいに、特定のシグニチャのメソッドを実装している型という制約もできる。
Java 2014/10/27
<T exnteds Bar>
でBar
またはBar
の任意のサブクラスを表す。
上限境界の例
public class Foo<T1 extends Bar, T2> {
...
}
複数の上限境界の例
public class Foo<T1 extends BarClass & IHoge1, T2> {
...
}
クラスBarClass
のサブクラスでかつインターフェースIHoge1
, IHoge2
を実装している型は
<T extends BarClass & IHoge1 & IHoge2>
と &
でつないで書く。&
で連結する型のうち、クラスは必ず先頭に書く。
Scala 2014/10/27
上限境界の例
class Foo[T1 <: Bar, T2] {
...
}
複数の上限境界の例 (いったん複数の上限を1つのクラスで定義してしまう)
class B extends BarClass with IHoge1;
class Foo[T1 <: B, T2] {
...
}
下限境界の例
class Foo[T1 >: Bar, T2] {
...
}