[转帖]scala day6_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3081 | 回复: 0   主题: [转帖]scala day6        下一篇 
只是很无聊
注册用户
等级:中尉
经验:440
发帖:33
精华:0
注册:2013-6-18
状态:离线
发送短消息息给只是很无聊 加好友    发送短消息息给只是很无聊 发消息
发表于: IP:您无权察看 2013-6-20 13:41:12 | [全部帖] [楼主帖] 楼主

11. case classes 以及模式匹配

11.1 case class


a:在class 前面加上case ,该class 就成为了case class
b:scala 编译器 首先为 这个类添加了一个工厂方法 用来 构造对象 ,
  这样允许 用户 不用使用new 就能构造对象
  例如:

Java代码  
北京联动北方科技有限公司

  1.  case class Var(name: String)  
  2.   scala> val v = Var("x")  
  3. v: Var = Var(x)  



c:在参数列表中的所有参数都隐含为val,因此 这些参数可以作为 字段加以维护
d:编译器为默认该类添加toString,hashcode equals 方法
e: 编译器为 该类 添加一个copy 方法,返回一个可以修改的copy 对象

11.2 pattern matching 模式匹配
a:定义模式匹配函数

 selector match { alternatives }


  每个alternatives 都是以case 开始
   每个alternatives 都包含 模式 以及表达式,,其中=> 将表达式和模式给分离出来

b:例如:

Java代码  
北京联动北方科技有限公司

  1.  def simplifyTop(expr: Expr): Expr = expr match { 
  2.       case UnOp("-", UnOp("-", e)) 
  3.       => e 
  4.       // Double negation 
  5.       case BinOp("+", e, Number(0)) => e // Adding zero 
  6.       case BinOp("*", e, Number(1)) => e // Multiplying by one 
  7.       case _ => expr 



c:  1.在scala 中match 是一个表达式
    2.在scala 中匹配一个pattern ,执行相关的expression,
       但是不会执行到 下一个case
    3.如果不能匹配到任何一个模式,则会抛出 MatchError 异常
    4. 因此 需要为case 定义一个默认 default case ,该case 什么也不处理
例如:

Java代码  
北京联动北方科技有限公司

  1.  expr match { 
  2. case BinOp(op, left, right) => 
  3. println(expr +" is a binary operation") 
  4. case _ => 


}

11.3 各种模式
a:_ 通配符匹配任何对象
b:constants pattern 常量模式:
  使用常量值作为模式串,例如:

Java代码  
北京联动北方科技有限公司

  1. def describe(x: Any) = x match { 
  2.       case 5 => "five" 
  3.       case true => "truth" 
  4.       case "hello" => "hi!" 
  5.       case Nil => "the empty list" 
  6.       case _ => "something else" 



c:variable pattern 变量模式
1.变量模式 就像通配符_一样,匹配任何对象
2.和同配符_不一样的是,变量和任何对象绑定在一起 ,你可以使用这些变量就像object 一样
  例如:

Java代码  
北京联动北方科技有限公司

  1.  expr match { 
  2.       case 0 => "zero" 
  3.       case somethingElse => "not zero: "+ somethingElse 



d:构造对象模式
  对象模式支持 多层的对象构造,也就是 deep  match,例如:

Java代码  
北京联动北方科技有限公司

  1.  expr match { 
  2.       case BinOp("+", e, Number(0)) => println("a deep match") 
  3.       case _ => 



e:sequence 模式
  1.匹配List 或者Array 这样的顺序类型
  2.使用相同的case 语法,但是可以指定模式了的元素个数,

例如:

Java代码  
北京联动北方科技有限公司

  1. expr match {  
  2. case List(0, _, _) => println("found it")  
  3. case _ =>  
  4. }  
  5. 匹配列表中的前三个元素  


3.使用_* 匹配任何长度的元素 ,例如:

Java代码  
北京联动北方科技有限公司

  1.  expr match {  
  2. case List(0, _*) => println("found it")  
  3. case _ =>  
  4. }  
  5. 与list 中的第0个元素匹配,而不管这个List 有多长  

e:Tuple pattern


例如:

Java代码  
北京联动北方科技有限公司

  1.  def tupleDemo(expr: Any) = 
  2. expr match { 
  3.       case (a, b, c) 
  4.       => 
  5.       println("matched "+ a + b + c) 
  6.       case _ => 
  7. scala> tupleDemo(("a ", 3, "-tuple")) 
  8. matched a 3-tuple 

f:Typed Pattern


1.方便做类型测试和类型转换
2.Map[_, _] 类型 在运行时,内部的类型会被同一转成 Object , 因此会碰到类型擦除的问题
3.但是Array[String] Array[Int]由于 在运行其使用的的底层机制是 String[] 或者int[] 类型,因此不会出现类型擦除的问题

例如:

Java代码  
北京联动北方科技有限公司

  1.  def generalSize(x: Any) = x match { 
  2.       case s: String => s.length 
  3.       case m: Map[_, _] => m.size 
  4.       case _ => -1 



Java代码  
北京联动北方科技有限公司

  1. def isIntIntMap(x: Any) = x match { 
  2.       case m: Map[Int, Int] => true 
  3.       case _ => false 
  4. scala> isIntIntMap(Map(1 -> 1)) 
  5. res19: Boolean = true 
  6. scala> isIntIntMap(Map("abc" -> "abc")) 
  7. res20: Boolean = true 



Java代码  
北京联动北方科技有限公司

  1. scala> def isStringArray(x: Any) = x match { 
  2.       case a: Array[String] => "yes" 
  3.       case _ => "no" 
  4. isStringArray: (x: Any)java.lang.String 
  5. scala> val as = Array("abc") 
  6. as: Array[java.lang.String] = Array(abc) 
  7. scala> isStringArray(as) 
  8. res21: java.lang.String = yes 
  9. scala> val ai = Array(1, 2, 3) 
  10. ai: Array[Int] = Array(1, 2, 3) 
  11. scala> isStringArray(ai) 
  12. res22: java.lang.String = no 



f.绑定变量
1. 变量名e+ 符号@+pattern 的形式,
pattern 完成普通的模式匹配,如果匹配成功,则将 被匹配的对象赋值给指定的变量
例如:

Java代码  
北京联动北方科技有限公司

  1.  expr match { 
  2.       case UnOp("abs", e @ UnOp("abs", _)) => e 
  3.       case _ => 



11.4 模式中的条件表达式
a: 在模式中 一个变量只允许出现一次
b:可以在模式中添加if 条件表达式 进行判断
例如:

Java代码  
北京联动北方科技有限公司

  1. def simplifyAdd(e: Expr) = e match { 
  2.       case BinOp("+", x, y) if x == y => 
  3.       BinOp("*", x, Number(2)) 
  4.       case _ => e 



Java代码  
北京联动北方科技有限公司

  1. // match only positive integers  
  2. case n: Int if 0 < n => ...  
  3. // match only strings starting with the letter ‘a’  
  4. case s: String if s(0) == 'a' => .  



11.5 pattern overlap 模式交叠
a:pattern 是根据他们写的顺序 进行匹配的。例如:

Java代码  
北京联动北方科技有限公司

  1.  def simplifyAll(expr: Expr): Expr = expr match { 
  2.       case UnOp("-", UnOp("-", e)) => 
  3.       simplifyAll(e) 
  4.       // ‘-’ is its own inverse 
  5.       case BinOp("+", e, Number(0)) => 
  6.       simplifyAll(e) 
  7.       // ‘0’ is a neutral element for ‘+’ 
  8.       case BinOp("*", e, Number(1)) => 
  9.       simplifyAll(e) 
  10.       // ‘1’ is a neutral element for ‘*’ 
  11.       case UnOp(op, e) => 
  12.       UnOp(op, simplifyAll(e)) 
  13.       case BinOp(op, l, r) => 
  14.       BinOp(op, simplifyAll(l), simplifyAll(r)) 
  15.       case _ => expr 



b:如果编译器检查到 之前的模式已经将所有的模式覆盖了,那么在这个模式之后定义的模式会被标注为unreachable code

11.6 sealed classes


a:为了得到编译器的帮助。列出所欲的模式组合,需要将case class 的父类定义为 sealed
b:加了sealed 关键字的class 除了那些在同一个文件中的子类外不允许添加任何子类
c:如果打算写一些用于模式匹配的类,应该考虑用sealed 封装 这些类的父类
例如:

Java代码  
北京联动北方科技有限公司

  1. sealed abstract class Expr  
  2. case class Var(name: String) extends Expr  
  3. case class Number(num: Double) extends Expr  
  4. case class UnOp(operator: String, arg: Expr) extends Expr  
  5. case class BinOp(operator: String,  
  6. left: Expr, right: Expr) extends Expr  



d:使用unchecked annotation 来避免编译器检查各种模式的组合,避免编译器发出这种警告,“ 表达式:@unchecked”例如

Java代码  
北京联动北方科技有限公司

  1. def describe(e: Expr): String = (e: @unchecked) match { 
  2.       case Number(_) => "a number" 
  3.       case Var(_) 
  4.       => "a variable" 



11.7 Option 类型
a:scala 为Option value 提供Option 类型,如果真实的值存在 则返回真实的值,否则返回None object

例如:

Java代码  
北京联动北方科技有限公司

  1. cala> val capitals = 
  2. Map("France" -> "Paris", "Japan" -> "Tokyo") 
  3. capitals: scala.collection.immutable.Map[java.lang.String, 
  4. java.lang.String] = Map(France -> Paris, Japan -> Tokyo) 
  5. scala> capitals get "France" 
  6. res23: Option[java.lang.String] = Some(Paris) 
  7. scala> capitals get "North Pole" 
  8. res24: Option[java.lang.String] = None 
  9. scala> def show(x: Option[String]) = x match { 
  10.       case Some(s) => s 
  11.       case None => "?" 
  12. show: (x: Option[String])String 
  13. scala> show(capitals get "Japan") 
  14. res25: String = Tokyo 
  15. scala> show(capitals get "France") 
  16. res26: String = Paris 
  17. scala> show(capitals get "North Pole") 
  18. res27: String = ? 

11.8 pattern every


1. 在变量定义中的模式 ,例如 在一个赋值中生成多个变量

Java代码  
北京联动北方科技有限公司

  1.  scala> val myTuple = (123, "abc")  
  2. myTuple: (Int, java.lang.String) = (123,abc)  
  3. scala> val (number, string) = myTuple  
  4. number: Int = 123  
  5. string: java.lang.String = abc  



2.在function 中的case squence,  为构造一个函数提供多个入口,见 Function1
例如:

Java代码  
北京联动北方科技有限公司

  1.  val withDefault: Option[Int] => Int = { 
  2.       case Some(x) => x 
  3.       case None => 0 
  4. scala> withDefault(Some(10)) 
  5. res28: Int = 10 
  6. scala> withDefault(None) 
  7. res29: Int = 0 



上述定义其实是 生成一个Function1 类

3.对于下面这种额外的情况: 在使用函数之前要先判断 输入的参数是否满足条件,如果满足,则该函数能够返回正确的值,否则则会抛出异常。对于这样的函数 外面可以定义为 :Parial Function
例如:

Java代码  
北京联动北方科技有限公司

  1. new PartialFunction[List[Int], Int] { 
  2.       def apply(xs: List[Int]) = xs match { 
  3.             case x :: y :: _ => y 
  4.       } 
  5.       def isDefinedAt(xs: List[Int]) = xs match { 
  6.             case x :: y :: _ => true 
  7.             case _ => false 
  8.       } 



4.例如:

Java代码  
北京联动北方科技有限公司

  1. val second: List[Int] => Int = { 
  2.       case x :: y :: _ => y 



second 函数对于list 中的元素<2 时,则会抛出异常。为了避免这种情况,可以将second 定义为Parital Function .

Java代码  
北京联动北方科技有限公司

  1. val second: PartialFunction[List[Int],Int] = { 
  2.       case x :: y :: _ => y 



那么在使用这个函数前就可以先用second.isDefinedAt 这个方法先判断是否满足条件,如果满足,之后在调用该函数

5. 表达式中的模式
例如 :

Java代码  
北京联动北方科技有限公司

  1. scala> for ((country, city) <- capitals)  
  2. println("The capital of "+ country +" is "+ city)  
  3. The capital of France is Paris  
  4. The capital of Japan is Tokyo  
  5. scala> val results = List(Some("apple"), None,  
  6. Some("orange"))  
  7. results: List[Option[java.lang.String]] = List(Some(apple),  
  8. None, Some(orange))  
  9. scala> for (Some(fruit) <- results) println(fruit)  
  10. apple  
  11. orang  



将集合内的元素展开,如果符合指定的模式,则输出,否则 不输出




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论