scala的语法糖

转载自:http://clojure.iteye.com/blog/2091818

scala这些语法糖在第一次看到,对于我们这些老编程人员来说,感觉有点莫名其妙,不过慢慢熟悉之后,就会感觉很自然。时间可以磨灭一些东西的。


对于scala搞那么多语法糖和新概念真是又爱又恨。爱的是scala引入了java一直没有的lambda特性,这对于使用高阶函数抽象来处理集合数据非常有爱(spark简洁的RDD处理得益于此)。恨的是scala搞那么多的新概念和语法糖。 

下面就来说说这些个语法糖和新概念: 

一、单例对象(singleton object) 

scala没有static关键字,搞出了个object关键字来新建单例对象。在单例对象中的成员都是static的。所以要写util类一般都要用这个东西。 

Scala代码   收藏代码
  1. object xxUtil{  
  2.    def process(xx:String):String = {  
  3.      xx  
  4.    }  
  5. }  

二、伴生对象和伴生类(companion object & companion class)、独立对象(standalone object)  

这两个概念是相互的。假设有object A 和 class A 两个同名了。这时候就可以说:object A是class A的“伴生对象”;class A是object A的“伴生类”。当一个object B没有同名的class B的时候,object B就叫“做独立对象”。 

伴生带来的特权就是:它们可以互相访问私有成员。 

class和object的区别: 
  1、单例对象不能用new来初始化。 
  2、单例对象不能带参数。 
  3、单例对象在第一次调用的时候才初始化。 

三、略坑的函数调用语法糖  

1、神奇的点号省略。 

虽然有的时候带来一定方便,不过组合lambda特性等东西,代码简直就能亮瞎你的氪金狗眼。 
Scala代码   收藏代码
  1. //无参数  
  2. "hello" toUpperCase  
  3. "hello".toUpperCase  
  4. "hello".toUpperCase()  
  5. //一个参数  
  6. "hello".indexOf "h"  
  7. "hello" indexOf "h"   
  8. //多个参数  
  9. "hello world" substring (03)   
  10. //全部搞在一起  
  11.  "hello world" substring (03)  toUpperCase() indexOf "h"  
  12. //配合上匿名函数  
  13. Array(1,2,3) map ((i:Int)=> i+1)  
  14.  1 to 3 map ((i:Int)=> i+1)  

2、神奇的for 
Scala代码   收藏代码
  1. //这个for挺正常的吧?  
  2. for(i <- 1 to 4) println(i)  
  3. //这个呢!  
  4.  for(i <- 1 to 4 if i > 1) println(i)  
  5. //这个呢!!!  
  6.  for(i <- 1 to 4 if i > 1; if i < 4; if i % 2 ==0) println(i)  

3、神奇的花括号{}代替小括号()语法 

据说,如果函数调用只传入一个参数,花括号可以代替小括号,scala粑粑不会打你屁股。 
Scala代码   收藏代码
  1. println("hello")  
  2. println{"hello"}  
  3.   
  4. def xx(i:Int)(j:Int) = i+j  
  5.  xx(1){2} //result: 3  
  6. (xx(1)_){3} //curry化调用  
  7. (xx(1)_)(3) //curry化调用,不信你不懵  
  8.   
  9. //看了上面的还没懵?那就再来个  
  10. def xx(i:Int)(j:(Int)=>Int) = j(i)  
  11. xx(1){i=> i+10}  
  12.   
  13. //有爱的一面  
  14. //假设我定义一个hbase的scan方法  
  15. def scan(tableName:String, cf:String, startRow:String, stopRow:String)(processFn:(Result)=>Unit) = {  
  16.   //...  
  17. }  
  18. //那么我可以这么自然的调用  
  19. scan(t1, cf, startRow, stopRow){ r =>  
  20.    //TODO process result  
  21. }  

4、神奇的byName函数和调用 

为了让自己定义的方法看起来和scala内建语法一样“和谐”,搞出了一个byName参数和byName函数。 
Scala代码   收藏代码
  1. //抄袭scala编程的例子  
  2.  def myAssert(pred:()=>Boolean) = if(!pred()) throw new AssertionError  
  3. myAssert(()=> 5<3) //()=> 5<3匿名函数看起来是不是不爽?  
  4.   
  5. //因为()=> 5<3 的调用看起来不自然。所以要将()这部分去掉。  
  6.  def myAssert2(pred: =>Boolean) = if(!pred) throw new AssertionError  
  7. myAssert2(5<3) // 这样看起来爽多了。  

四、类型的上下界  

class foo[T <% A]{...} //弱上界<%。关系较弱:T能够隐式转换为Ordered[T] 
class foo[T <: A]{...} //上界 <:。T必须是A的子类,A是T的类型上界。 
class foo[T >: A]{...} //下界 >:。T必须是A的父类,A是T类型的下界。 

五、协变和逆变  

+T: 协变:class Queue[+T] {}。如果C<:A,则Queue[C] <: Queue[A]  
-T: 逆变 : class Queue[-T] {}。如果C<:A,则Queue[C] >: Queue[A] 

六、隐式转换  

隐式转换,是对应于显式的转换来说的。比如有"1234".toInt,这就是显式的转换,不直接调用toInt方法转换的就是隐式转换。 

Scala代码   收藏代码
  1. implicit def str2Int(s:String):Int = Integer.parseInt(s) //隐式str转int  
  2. def add(a:Int, b:Int) = a+b  
  3. add("1",2) //先把"1"隐式转换为1,再加起来。  

七、case类  

case类是什么,case类就是一个class,可是能用来做模式匹配。所以搞出这么个东西。。。 

case类和一般类的不同点: 
1、会有和类名一样的工厂方法。不需要使用new来创建这个类对象。 
Scala代码   收藏代码
  1. case class Var(name:String)  
  2. val v1 = Var("peter") //和类名一样的工厂方法  

2、case类的参数列表默认是val的。 
3、自动添加了toString,hashCode和equals的自然实现。 

case类的最大的用途就是用来做模式匹配。 
Scala代码   收藏代码
  1. case class Var(name:String)  
  2. val v1 = Var("peter")  
  3. v1 match {  
  4.    case Var(name) => name  
  5.    case _ =>  
  6. }  
  7. //匹配出name为peter  

八、模式守卫  

模式守卫(pattern guard)接pattern之后,开始与if。只有模式守卫返回true才算成功。 
Scala代码   收藏代码
  1. 10 match {  
  2.   case n:Int if 1< n => println(n) //if到=>之前,这段为模式守卫  
  3.   case _ =>  
  4. }  

你可能感兴趣的:(scala,scala,语法糖)