Scalaにはパスに依存する型があると聞きました。これは内部クラスと関係があるのですが、これは実際には何を意味し、なぜ私は気にするのですか?
私のお気に入りの例:
case class Board(length: Int, height: Int) {
case class Coordinate(x: Int, y: Int) {
require(0 <= x && x < length && 0 <= y && y < height)
}
val occupied = scala.collection.mutable.Set[Coordinate]()
}
val b1 = Board(20, 20)
val b2 = Board(30, 30)
val c1 = b1.Coordinate(15, 15)
val c2 = b2.Coordinate(25, 25)
b1.occupied += c1
b2.occupied += c2
// Next line doesn't compile
b1.occupied += c2
したがって、Coordinate
のタイプは、インスタンス化されたBoard
のインスタンスに依存します。これで達成できるすべての種類のものがあり、型のみではなく値に依存する一種の型安全性を提供します。
これは依存型のように聞こえるかもしれませんが、より制限されています。たとえば、occupied
のタイプはBoard
の値に依存します。上記では、occupied
のタイプがc2
であるのに対し、b2.Coordinate
のタイプはSet[b1.Coordinate]
であるため、最後の行は機能しません。同じタイプのb1
を持つ別の識別子を使用できるため、そのタイプに関連付けられているのはidentifierb1
ではないことに注意してください。たとえば、次の作品:
val b3: b1.type = b1
val c3 = b3.Coordinate(10, 10)
b1.occupied += c3