package chap15 sealed abstract class Expr // 加了sealed,其他文件里不能extends Expr case class Var(name: String) extends Expr case class Number(num: Double) extends Expr case class UnOp(operator: String, arg: Expr) extends Expr case class BinOp(operator: String, left: Expr, right: Expr) extends Expr object Chap15 { def main(args: Array[String]) { case class XXExpr extends Expr // 在同一file的 不同地方可以extends sealed class /* * case class有几个好处 */ // 1. factory method val expr = BinOp("+", Number(1), Var("x")) // 2. get val prefix val num = expr.left // 3. structural toString, hashCode, equals println(expr.right == Var("x")) // true // 4. copy method val expr2 = expr.copy("-") val expr3 = expr.copy(left = Number(2)) println(expr2, expr3) /* * 15.2 kinds of patterns */ // 1. wildcard patterns val exprStr = expr match { case BinOp("+", a, b) => println(a, b); a case _ => // 什么都不需要写,() } println(exprStr) // 2. constant patterns def describe(x: Any) = x match { case 5 => "five" case true => "truth" case "hello" => "hi!" case Nil => "the empty list" case _ => "something else" } // 3. Variable patterns /* matches any object, just like a wildcard, 有名字可以引用 * a simple name starting with a lowercase letter is taken to be a pattern variable; * all other references are taken to be constants. */ val Pi = 3.14 val E = 2.71 val pi = Pi //> pi : Double = 3.14 E match { case Pi => "strange?!" case _ => "Ok" } E match { case pi => "strange?!" case _ => "Ok" } E match { case `pi` => "strange?!" case _ => "Ok" } // 4. Constructor patterns, deep matches // 5. Sequence patterns expr match { case List(0, _, _*) => println("found it") case _ => } // 6. Tuple patterns def tupleDemo(expr: Any) = expr match { case (a, b, c) => println("matched " + a + b + c) case _ => } // 7. Typed patterns /* * 比expr.isInstanceOf[String]然后expr.asInstanceOf[String]好 */ def generalSize(x: Any) = x match { case s: String => s.length case m: Map[_, _] => m.size case _ => -1 } println(generalSize(null: String)) // it matches every (non-null) instance of String. val typedValue: Any = List("a", "b") //> typedValue : Any = List(a, b) val typed = typedValue match { case s: List[_] => s.length // List[Int]或者List[String]都没有用,type erasure case _ => 1 } //> typed : Int = 2 val typedValueArr: Any = Array("a", "b", "c") //> typedValueArr : Any = Array(a, b, c) // val typedValueArr: Any = Array(1, 2, 3) val typedArr = typedValueArr match { case s: Array[Int] => s.length // The element type of an array is stored with the array value, so you can pattern match on it case _ => 1 } // 8.Variable binding val expr4: Expr = expr expr4 match { case UnOp("abs", e @ UnOp("abs", _)) => e case _ => } // 15.3 Pattern guards def simplifyAdd(e: Expr) = e match { case BinOp("+", x, y) if x == y => // 不能用BinOp("+", x, x),Scala restricts patterns to be linear: a pattern variable may only appear once in a pattern. BinOp("*", x, Number(2)) case _ => e } // 15.4 Pattern overlaps /* * it is important that the catch-all cases come after the * more specific simplification rules. */ // 15.5 Sealed classes def describe2(e: Expr): String = (e: @unchecked) match { //sealed帮助编译检查,没有@unchecked会有编译warning case Number(_) => "a number" case Var(_) => "a variable" } // 15.7 Patterns everywhere // 1. variable definitions val myTuple = (123, "abc") val (number, string) = myTuple // 2. Case sequences as partial functions // If the declared type is just Function1, or is missing, // the function literal is instead translated to a complete function. val second: PartialFunction[List[Int], Int] = { // List[Int] => Int会有warning case x :: y :: _ => y } println(second.isDefinedAt(List(5))) /* * In fact, such an expression gets translated by the Scala compiler to a partial function * by translating the patterns twice */ val second2 = new PartialFunction[List[Int], Int] { def apply(xs: List[Int]) = xs match { case x :: y :: _ => y } def isDefinedAt(xs: List[Int]) = xs match { case x :: y :: _ => true case _ => false } } println(second2.isDefinedAt(List(5, 6))) println(second2(List(5, 6, 7))) // 3. Patterns in for expressions val results = List(Some("apple"), None, Some("orange")) for (Some(x) <- results) println(x) // 不会有None, generated values that do not match the pattern are discarded. F } }