高阶函数
Scala 混合了面向对象和函数式的特性,我们通常将可以作为参数传递到方法中的表达式叫做函数
作为值的函数
val arr = Array(1,2,3,4) val f1 = (x:Int) => x*2 arr.map(f1)//Array(2,4,6,8)
匿名函数
arr.map((x:Int)=>x*2)//Array(2,4,6,8) arr.map(x=>x*2)//Array(2,4,6,8) arr.map(_*2)//Array(2,4,6,8)
柯里化
- 柯里化(Currying)指的是把原来接受多个参数的函数变换成接受一个参数的函数过程,并且返回接受余下的参数且返回结果为一个新函数的技术。
- scala 柯里化风格的使用可以简化主函数的复杂度,提高主函数的自闭性,提高功能上的可扩张性、灵活性。可以编写出更加抽象,功能化和高效的函数式代码。
//定义一个方法, 方法有一个Int参数,方法体是一个函数 def m(x:Int)=(y:Int)=>x*y //调用方法传入Int参数返回一个函数 val f=m(3) //调用函数,返回结果 val v=f(5) //15 //简写 def m(x:Int)(y:Int)=x*y //调用 val v=m(3)(5) //15 //当你调用 m(3)(5)时,实际上是依次调用两个普通函数(非柯里化函数), //第一次调用使用一个参数 x,返回一个函数类型的值, //第二次使用参数 y 调用这个函数类型的值。 //也可以使用下划线“_” 作为第二参数列表的占位符, 这个定义的返回值为一个函数, //当调用时会给调用的参数加一。 val f=m(3)_ val v=f(5) //15
闭包
- 闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
- 闭包通常来讲可以简单的认为是可以访问不在当前作用域范围内的一个函数。
val y=10 val add=(x:Int)=>{ // 然而,y 不是形式参数,而是自由变量 x+y } val v=add(5)//15
隐式转换和隐式参数
隐式转换
允许你手动指定,将某种类型的对象转换成其他类型的对象或者是给一个类增加方法
Scala 的隐式转换,其实最核心的就是定义隐式转换方法,即 implicitconversion function。定义的隐式转换方法,只要在编写的程序内引入,就会被Scala 自动使用。Scala 会根据隐式转换方法的签名,在程序中使用到隐式转换方法接收的参数类型定义的对象时,会自动将其传入隐式转换方法,转换为另外一种类型的对象并返回。这就是“隐式转换”。其中所有的隐式值和隐式方法必须放到 object 中。
- implicit 关键字只能用来修饰方法、变量(参数)。
- 隐式转换的方法在当前范围内才有效。如果隐式转换不在当前范围内定义比如定义在另一个类中或包含在某个对象中),那么必须通过 import 语句将其导入
隐式参数
所谓的隐式参数,指的是在函数或者方法中,定义一个用 implicit 修饰的参数,此时 Scala 会尝试找到一个指定类型的,用 implicit 修饰的参数,即隐式值,并注入参数。
Scala 会在两个范围内查找:
- 当前作用域内可见的 val 或 var 定义的隐式变量
- 一种是隐式参数类型的伴生对象内的隐式值
隐式转换方法作用域与导入
Scala 默认会使用两种隐式转换,一种是源类型或者目标类型的伴生对象内的隐式转换方法;一种是当前程序作用域内的可以用唯一标识符表示的隐式转换方法。
如果隐式转换方法不在上述两种情况下的话,那么就必须手动使用import 语法引入某个包下的隐式转换方法,比如 import test._。通常建议,仅仅在需要进行隐式转换的地方,用 import 导入隐式转换方法,这样可以缩小隐式转换方法的作用域,避免不需要的隐式转换。隐式转换的时机
- 当对象调用类中不存在的方法或成员时,编译器会自动将对象进行隐式转换
- 当方法中的参数的类型与目标类型不一致时
class Man(val name:String) class SuperMan(val name: String) { def heat=print("超人打怪兽") } object SuperMan{ //隐式转换方法 implicit def man2SuperMan(man:Man)=new SuperMan(man.name) def main(args: Array[String]) { val hero=new Man("hero") //Man具备了SuperMan的方法 hero.heat } }
object Company{ //在object中定义隐式值 注意:同一类型的隐式值只允许出现一次,否则会报错 implicit val xxx="zhangsan" implicit val yyy=10000.00 } class Boss { //定义一个用implicit修饰的参数 类型为String //注意参数匹配的类型 它需要的是String类型的隐式值 def callName()(implicit name:String):String={ name+" is coming !" } //定义一个用implicit修饰的参数,类型为Double //注意参数匹配的类型 它需要的是Double类型的隐式值 def getMoney()(implicit money:Double):String={ " 当月薪水:"+money } } object Boss extends App{ //使用import导入定义好的隐式值,注意:必须先加载否则会报错 import Company._ val boss =new Boss println(boss.callName()+boss.getMoney()) }