#apply方法# 当类或对象有一个主要用途时,apply方法提供一个很好的俄语法糖。
scala> class Foo{}defined class Fooscala> object Foomaker{ | def apply()=new Foo | } defined module Foomakerscala> val newFoo =FooMaker():7: error: not found: value FooMaker val newFoo =FooMaker() ^scala> val newFoo = FooMaker() :7: error: not found: value FooMaker val newFoo = FooMaker() ^scala> val newFoo = Foomaker()newFoo: Foo = Foo@5d4aa6eb
或者:
scala> class Bar{ | def apply()=0 | } defined class Barscala> val bar =new Barbar: Bar = Bar@6704e2a0scala> bar()res0: Int = 0
在这里,实例化对象看起来像是在调用一个方法。
#单例对象# 单例对象用于持有一个类的唯一的实例。通常用于工厂模式。
scala> object Timer{ | var count=0 | def currentCount():Long={ | count+=1 | count | } | } defined module Timer
可以这样使用:
scala> Timer.currentCount()res1: Long = 1scala> Timer.currentCount()res2: Long = 2scala> Timer.currentCount()res3: Long = 3
单例对象可以和类具有相同的名称,此时该对象也被称为“伴生对象".通常将伴生对象作为工厂使用。 下面是一个简单的例子,可以不需要使用new来创建一个示例了。
scala> class Bar(foo:String)defined class Barscala> object Bar{ | def apply(foo:String)=new Bar(foo)\ | }:9: error: value \ is not a member of Bar def apply(foo:String)=new Bar(foo)\ ^scala> object Bar{ | def apply(foo:String)=new Bar(foo) | } defined module Bar warning: previously defined class Bar is not a companion to object Bar. Companions must be defined together; you may wish to use :paste mode for this.
#函数即对象# 在scala中,我们经常讨论对象的函数时编程。这是什么意思?到底说明是函数呢?
函数时一些特质的集合。具体来说,具有一个参数的函数是Function1特质的一个示例。这个特征定义了apply()语法糖,让你调用一个对象时就像你在调用一个函数。
scala> object addOne extends Function1[Int,Int]{ | def apply(m:Int):Int=m+1 | } defined module addOnescala> addOne(2)res4: Int = 3
这个Function特质集合下标从0开始一直到22,为什么是22,这是一个主观的魔幻数字(magic number),我从来没有使用过多余22个参数的函数,所以这个数字似乎时合理的。
apply语法糖有助于统一对象和函数时编程的二重性。你可以传递类,并把他们当作函数使用,而函数本质上是类的实例。
这是否意味着,当你在类中定义一个方法时,得到的实际上是一个Function的实例?不是的,在类中定义的方法是方法而不是函数。在repl中独立定义的方法是Function的实例。
类也可以扩展Function,这些类的实例可以使用()调用。
scala> class addOne extends Function1[Int,Int]{ | def apply(m:Int):Int=m+1 | } defined class addOne warning: previously defined object addOne is not a companion to class addOne. Companions must be defined together; you may wish to use :paste mode for this.scala> val plusOne=new addOne()plusOne: addOne =scala> plusOne(2)res5: Int = 3
可以使用更直观快捷的extends(Int => Int)代替extends Function1[Int,Int}
scala> class AddOne extends (Int => Int){ | def apply(m:Int):Int=m+1 | } defined class AddOne
#包# 你可已将代码组织在包中。 package com.king.demo
在文件头部定义包,会将文件中所有的代码申明在那个包中。 值和函数不能在类或者单例对象之外定义。单例对象时组织静态函数(static function)的有效工具。
package com.king.demoobject colorHolder{ val BLUE="blue" val RED="red"}
现在你可以直接访问这些成员。
println("the color is " +com.king.demo.colorHolder.BLUE)
注意在你定义这个对象时scala解释器的返回:
scala> object colorHolder{ | val Blue="blue" | val Red="red" | } defined module colorHolder
这暗示了scala的设计者是把对象作为scala的模块系统的一部分进行涉及的。
#模式匹配# 这是scala中最有用的部分之一。 匹配值
scala> times match{ | case 1=>"one" | case 2=>"two" | case _=>"some other number" | } res6: String = one
使用守卫进行匹配
scala> times match { | case i if i==1=>"one" | case i if i==2=>"two" | case _=> "some other number" | } res7: String = one
注意我们是怎样将值赋给变量i的。
在最后一行的指令中的_时一个通配符:他保证了我们可以处理所有的情况。 否则当传进一个不能匹配的数字的时候,你将获得一个运行时错误。
##类型匹配## 你可以使用match来分别处理不同类型的值。
scala> def bigger(o:Any):Any={ | o match { | case i:Int if i<0=>i-1 | case i:Int => i+1 | case d:Double if d<0.0 => d-0.1 | case d:Double => d+0.1 | case text:String => text+" s" | } | } bigger: (o: Any)Any
###匹配类成员###
#样本类# #异常处理#