ジェネリクス

Scalaの「ジェネリクス(Generics)」とは、データ型に依存しない汎用的なコードを記述するための仕組みであり、型パラメータを用いてクラス、トレイト、メソッドなどを定義できます。これにより、型安全性を保ちつつ、再利用性の高い柔軟なコードを書くことが可能になります。


1. 基本構文

Scalaでは、クラスやメソッドの定義時に[T]のような構文で型パラメータを指定します。

クラスのジェネリクス例

scala
class Box[T](value: T) { def get: T = value }

上記のBoxクラスは、任意の型Tを受け取り、その型の値を保持し取得する機能を提供します。

使用例

scala
val intBox = new Box val strBox = new Box[String]("hello") println(intBox.get) // 123 println(strBox.get) // hello

2. メソッドにおけるジェネリクス

メソッド単位でもジェネリクスを使用できます。

scala
def identity[T](x: T): T = x val a = identity(10) // Int val b = identity("Scala") // String

ここではidentityメソッドが与えられた引数をそのまま返しますが、型をTとして抽象化しているため、任意の型で利用可能です。


3. 複数の型パラメータ

複数の型をパラメータとして扱うことも可能です。

scala
class Pair[A, B](val first: A, val second: B) val pair = new Pair[Int, String](1, "one")

4. 型境界(型制約)

Scalaでは型パラメータに**境界(bounds)**を設けて、ある型のサブ型またはスーパー型に限定することができます。

上限境界(Upper Bound)

scala
class Animal class Dog extends Animal class Cage[T <: Animal](val animal: T) val cage = new Cage(new Dog)

ここではT <: Animalにより、TはAnimalのサブクラスでなければならないという制約がかかっています。

下限境界(Lower Bound)

scala
def addToList[T >: Dog](list: List[T], dog: Dog): List[T] = dog :: list

T >: Dogにより、TはDogのスーパークラスでなければならないと制限しています。


5. 协変(covariance)と反変(contravariance)

Scalaのジェネリクスでは、**型パラメータの変性(variance)**を指定できます。

  • +T: 協変(Covariant) – Tが変わればこのクラスの型も変わる

  • -T: 反変(Contravariant) – Tが広がればこのクラスの型が狭まる

  • T: 不変(Invariant) – 型はそのまま

scala
class Covariant[+T] // 協変 class Contravariant[-T] // 反変 class Invariant[T] // 不変(デフォルト)

6. 型クラス風の利用(コンテキスト境界)

Scalaでは**コンテキスト境界(context bound)**を使って、暗黙の型クラスインスタンスを受け取るような設計ができます。

scala
def maxList[T: Ordering](elements: List[T]): T = elements.max

これは「Ordering[T]型のインスタンスが暗黙に存在すること」が前提の制約です。


まとめ

機能 説明
T 汎用の型パラメータ
[T <: 上限型] 型の上限を指定(サブタイプのみ許容)
[T >: 下限型] 型の下限を指定(スーパークラスを許容)
+T 協変(Listはその典型)
-T 反変(関数引数に多い)
[T: TypeClass] コンテキスト境界(暗黙の型クラス)

ScalaのジェネリクスはJavaよりも表現力が高く、関数型スタイルにもよく適合しています。

生成日:2025/05/04