String // 各ユーザーに付与されるユニークな ID def createdAt: Date // このユーザーがサイトにはじめて訪れた日付 // 訪問者がどのくらいの時間そこにいたか? def age: Long = new Date().getTime - createdAt.getTime } Visitor は2つの抽象メソッドを規定しています。メソッドは実装を持ちませんが、派生クラ スで実装されなければなりません。その対象として id と createdAt があります。また、ひ とつの抽象メソッドを項として定義に含む、具象メソッドである age を定義しています。
id: String def createdAt: Date def age: Long = new Date().getTime() - createdAt.getTime() } case class User(id: String, email: String, createdAt: Date = new Date()) extends Visitor case class Anonymous(id: String, createdAt: Date = new Date()) extends Visitor
match { case User(_, _, _) => "Got a user" } // <console>:15: warning: match may not be exhaustive. // It would fail on the following input: Anonymous(_, _) // def missingCase(v: Visitor) = v match { // ^ // missingCase: (v: Visitor)String
法があります。 「A は D を持ち、D は B か C である」と言えます。これを実装するために2つのパターン を機械的に適用することができます。 trait A { def d: D } sealed trait D final case class B() extends D final case class C() extends D
def foo: String = "It's A!" } final case class B() extends A { override def foo: String = "It's B!" } final case class C() extends A { override def foo: String = "It's C!" }
を持ち、F 型を返すメソッド f を記述したい場合、シンプルに いつもの方法でメソッドを記述する。 case class A(b: B, c: C) { def f: F = ??? } メソッドの本体で、F 型の結果を構築するために、 b と c とメソッド引数を必ず使用しな ければならない。 48
で f を抽象メソッドとして 定義し、B と C で具象実装を提供する。 sealed trait A { def f: F } final case class B() extends A { def f: F = ??? } final case class C() extends A { def f: F = ??? } 49
final case class Lion() extends Feline { def dinner: Food = Antelope } final case class Tiger() extends Feline { def dinner: Food = TigerFood } final case class Panther() extends Feline { def dinner: Food = Licorice } final case class Cat(favouriteFood: String) extends Feline { def dinner: Food = CatFood(favouriteFood) }
this match { case Lion() => Antelope case Tiger() => TigerFood case Panther() => Licorice case Cat(favouriteFood) => CatFood(favouriteFood) } } final case class Lion() extends Feline final case class Tiger() extends Feline final case class Panther() extends Feline final case class Cat(favouriteFood: String) extends Feline
Feline final case class Tiger() extends Feline final case class Panther() extends Feline final case class Cat(favouriteFood: String) extends Feline object Diner { def dinner(feline: Feline): Food = feline match { case Lion() => Antelope case Tiger() => TigerFood case Panther() => Licorice case Cat(food) => CatFood(food) } }
最後を表すベースケースを定義することで妥当な再帰的データを定義できます。 sealed trait IntList final case object End extends IntList final case class Pair(head: Int, tail: IntList) extends IntList Pair(1, Pair(2, Pair(3, End))) // res: Pair = Pair(1,Pair(2,Pair(3,End)))
list match { case End => 0 case Pair(hd, tl) => hd + sum(tl) } // <console>:18: error: could not optimize @tailrec annotated method sum: it ... // def sum(list: IntList): Int = list match { // ^ @tailrec def sum(list: IntList, total: Int = 0): Int = list match { case End => total case Pair(hd, tl) => sum(tl, total + hd) } // sum: (list: IntList, total: Int)Int