Scala基础:闭包、柯里化、隐式转换和隐式参数

Scala基础:闭包、柯里化、隐式转换和隐式参数

闭包,和js中的闭包一样,返回值依赖于声明在函数外部的一个或多个变量,那么这个函数就是闭包函数。

    val i: Int = 20
    //函数func的方法体中使用了在func外部定义的变量 那func就是个闭包函数
    val func = (x: Int) => x + i

 

柯里化(Currying)指的是把原来接受多个参数的函数变换成接受一个参数的函数过程,并且返回接受余下的参数且返回结果为一个新函数的技术。柯里化并不是scala特有的,js中也有。

package com.zy.scala

object CurryingDemo {
  def main(args: Array[String]): Unit = {

    //原本的方法
    def m(x: Int, y: Int) = x + y


    //第一种柯里化
    def first(x: Int) = (y: Int) => x + y

    val second = first(1)
    val result: Int = second(2)
    println(result)

    //第二种柯里化
    def curriedSum(x: Int)(y: Int) = x + y

    val sum: Int = curriedSum(1)(2)
    println(sum)

  }
}

 

Scala 提供的隐式转换和隐式参数功能,是非常有特色的功能。是 Java 等编程语言所没有的功能。它可以允许你手动指定,将某种类型的对象转换成其他类型的对象或者是给一个类增加方法。通过这些功能,
可以实现非常强大、特殊的功能。 Scala 的隐式转换,其实最核心的就是定义隐式转换方法,即 implicit conversion function。定义的隐式转换方法,只要在编写的程序内引入,就会被Scala 自动使用。Scala 会根据隐式转换方法的签名,
在程序中使用到隐式转换方法接收的参数类型定义的对象时,会自动将其传入隐式转换方法,转换为另外一种类型的对象并返回。这就是“隐式转换”。其中所有的隐式值和隐式方法必须放到 object 中。 然而使用 Scala 的隐式转换是有一定的限制的,总结如下:   implicit 关键字只能用来修饰方法、变量(参数)。   隐式转换的方法在当前范围内才有效。如果隐式转换不在当前范围内定义(比如定义在另一个类中或包含在某个对象中),那么必须通过
import 语句将其导。 所谓的隐式参数,指的是在函数或者方法中,定义一个用 implicit 修饰的参数,此时 Scala 会尝试找到一个指定类型的,用 implicit 修饰的参数,即隐式值,并注入参数。 Scala 会在两个范围内查找:   当前作用域内可见的 val 或 var 定义的隐式变量;   一种是隐式参数类型的伴生对象内的隐式值;

 

隐式参数案例

package com.zy.scala

object Company {
  //在 object 中定义隐式值 注意:同一类型的隐式值只允许出现一次,否则会报错
  implicit val aaa = "zhangsan"
  implicit val bbb = 10000.00
}

class Boss {
  //注意参数匹配的类型 它需要的是 String 类型的隐式值
  def callName()(implicit name: String): String = {
    name + " is coming !"
  }

  //定义一个用 implicit 修饰的参数
  //注意参数匹配的类型 它需要的是 Double 类型的隐式值
  def getMoney()(implicit money: Double): String = {
    " 当月薪水:" + money
  }
}

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

  val boss = new Boss
  println(boss.callName() + boss.getMoney())
}

 

隐式转换

package com.zy.scala

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("E://words.txt")
    //使用 import 导入隐式转换方法
    import MyPredef._
    //通过隐式转换,让 File 类具备了 RichFile 类中的方法
    val content = f.read()
    println(content)
  }
}
package com.zy.scala

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
  }
}
package com.zy.scala

class A(c: C) {
  def readBook(): Unit = {
    println("A 说:好书好书...")
  }
}

class B(c: C) {
  def readBook(): Unit = {
    println("B 说:看不懂...")
  }

  def writeBook(): Unit = {
    println("B 说:不会写...")
  }
}

class C

object AB {
  //创建一个类的 2 个类的隐式转换
  implicit def C2A(c: C) = new A(c)

  implicit def C2B(c: C) = new B(c)
}

object B {
  def main(args: Array[String]) {
    //导包
    //1. import AB._ 会将 AB 类下的所有隐式转换导进来
    //2. import AB._C2A 只导入 C 类到 A 类的的隐式转换方法
    //3. import AB._C2B 只导入 C 类到 B 类的的隐式转换方法
    import AB._
    val c = new C
    //由于 A 类与 B 类中都有 readBook(),只能导入其中一个,否则调用共同方法时代码报错
    //c.readBook()
    //C 类可以执行 B 类中的 writeBook()
    c.writeBook()
  }
}

 

posted @ 2018-10-17 19:59 青衫仗剑 阅读( ...) 评论( ...) 编辑 收藏

你可能感兴趣的:(Scala基础:闭包、柯里化、隐式转换和隐式参数)