Scala学习(二)

Scala的一些高级特性

高阶函数

通常将可以作为参数传递到方法中的表达式叫做函数。在函数式编程语言中,函数是“头等公民”,高阶函数包含:作为值的函数、匿名函数、闭包、柯里化等等。

  1. 作为值的函数&匿名函数
    可以像任何其他数据类型一样被传递和操作的函数,每当你想要给算法传入具体动作时这个特性就会变得非常有用。
val arr = Array(1, 2, 3, 4, 5)
val f1 = (x: Int) => x * 2
//作为值的函数
val arr1: Array[Int] = arr.map(f1)

//匿名函数
val arr2: Array[Int] = arr.map((x: Int) => x * 2)
//也可以简写为
val arr3: Array[Int] = arr.map(_ * 2)
  1. 柯里化
    柯里化(Currying)指的是把原来接受多个参数的函数变换成接受一个参数的函数过程,并且返回接受余下的参数且返回结果为一个新函数。

scala柯里化风格的使用可以简化主函数的复杂度,提高主函数的自闭性,提高功能上的可扩张性、灵活性。可以编写出更加抽象,功能化和高效的函数式代码。

//定义一个加法计算
//def m1(x: Int) = (y: Int) => x + y
def m1(x: Int)(y: Int) = x + y
//传入两个参数得到结果
val i: Int = m1(1)(2)

//实际上在调用m1(1)(2)的过程是以下步骤
//传入一个参数后变成了一个新函数(接受多个参数的函数变换成接受一个参数的函数)
val f1: Int => Int = m1(1)
//调用新生成的函数得到计算结果
val i1: Int = f1(2)
  1. 闭包
    闭包是一个函数返回值依赖于声明在函数外部的一个或多个变量。通常来讲可以简单的认为是可以访问不在当前作用域范围内的一个函数。
val y = 2
//变量y不处于其有效作用域时,函数还能够对变量进行访问
//在add中有两个变量:x和y。x是函数的形式参数,y是一个自由变量
val add = (x: Int) => x + y

println(add(1)) //3
隐式转换和隐式参数
  1. 隐式转换
    Scala提供的隐式转换和隐式参数功能,是非常有特色的功能。是Java等编程语言所没有的功能。它可以允许你手动指定,将某种类型的对象转换成其他类型的对象或者是给一个类增加方法。通过这些功能,可以实现非常强大、特殊的功能。

    Scala的隐式转换,其实最核心的就是定义隐式转换方法,即implicit conversion function。定义的隐式转换方法,只要在编写的程序内引入,就会被Scala自动使用。Scala会根据隐式转换方法的签名,在程序中使用到隐式转换方法接收的参数类型定义的对象时,会自动将其传入隐式转换方法,转换为另外一种类型的对象并返回。这就是“隐式转换”。其中所有的隐式值和隐式方法必须放到object中

    然而使用Scala的隐式转换是有一定的限制的,总结如下:

    • implicit关键字只能用来修饰方法、变量(参数)。
    • 隐式转换的方法在当前范围内才有效。如果隐式转换不在当前范围内定义(比如定义在另一个类中或包含在某个对象中),那么必须通过import语句将其导。
  2. 隐式参数
    隐式参数指的是在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会尝试找到一个指定类型的,用implicit修饰的参数,即隐式值,并注入参数。
    Scala会在两个范围内查找:

    • 当前作用域内可见的val或var定义的隐式变量;
    • 一种是隐式参数类型的伴生对象内的隐式值;
  3. 隐式转换方法作用域与导入
    (1)Scala默认会使用两种隐式转换,一种是源类型,或者目标类型的伴生对象内的隐式转换方法;一种是当前程序作用域内的可以用唯一标识符表示的隐式转换方法。
    (2)如果隐式转换方法不在上述两种情况下的话,那么就必须手动使用import语法引入某个包下的隐式转换方法,比如import test._。通常建议,仅仅在需要进行隐式转换的地方,用import导入隐式转换方法,这样可以缩小隐式转换方法的作用域,避免不需要的隐式转换。

  4. 隐式转换的时机
    (1)当对象调用类中不存在的方法或成员时,编译器会自动将对象进行隐式转换
    (2)当方法中的参数的类型与目标类型不一致时

隐式转换:让File类具备RichFile类中的read方法

import java.io.File
import scala.io.Source

object MyPredef{
  //定义隐式转换方法
  implicit def file2RichFile(file: File)=new RichFile(file)
}
class RichFile(val f:File) {
  def read()=Source.fromFile(f).mkString
}
object RichFile{
  def main(args: Array[String]) {
    val f=new File("D://words.txt")
    //使用import导入隐式转换方法
    //import MyPredef._
    import MyPredef.file2RichFile
    //通过隐式转换,让File类具备了RichFile类中的方法
    val content=f.read()
    println(content)
  }
}

如果一个类隐式转换成具有相同方法的多个类,在导入时只能导入其中一个,否则调用共同方法时代码报错

隐式参数:在定义隐式值时同一类型的隐式值只允许出现一次,否则会报错

object Value {
  //在object中定义隐式值;同一类型的隐式值只允许出现一次,否则会报错!
  implicit val aaa = "zhangsan"
  implicit val bbb = 18
}

class Person {
  //使用implicit修饰参数
  //注意参数匹配的类型是String类型的隐式值
  def getName()(implicit name: String): String = {
    "姓名:" + name
  }

  //注意参数匹配的类型是Double类型的隐式值
  def getAge()(implicit age: Int): String = {
    "年龄:" + age
  }
}

object Person extends App {
  //使用import导入定义好的隐式值,必须先加载否则会报错
  import Value._

  val p = new Person
  println(p.getName() + p.getAge())
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值