Słyszałem, że Scala ma typy zależne od ścieżki. To ma coś wspólnego z klasami wewnętrznymi, ale co to właściwie oznacza i dlaczego mnie to obchodzi?
Słyszałem, że Scala ma typy zależne od ścieżki. To ma coś wspólnego z klasami wewnętrznymi, ale co to właściwie oznacza i dlaczego mnie to obchodzi?
Odpowiedzi:
Mój ulubiony przykład:
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
Tak więc typ Coordinate
jest zależny od instancji, Board
z której została utworzona. Jest wiele rzeczy, które można w ten sposób osiągnąć, dając rodzaj bezpieczeństwa zależnego od wartości, a nie samych typów.
Może to brzmieć jak typy zależne, ale jest bardziej ograniczone. Na przykład typ occupied
zależy od wartości Board
. Powyżej ostatnia linia nie działa, ponieważ typ c2
to b2.Coordinate
, a occupied
typ to Set[b1.Coordinate]
. Należy zauważyć, że można użyć innego identyfikatora tego samego typu b1
, więc nie jest to identyfikator b1
powiązany z typem. Na przykład działa to:
val b3: b1.type = b1
val c3 = b3.Coordinate(10, 10)
b1.occupied += c3