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()
}
}
Scala基础:闭包、柯里化、隐式转换和隐式参数的更多相关文章
- Scala中的柯里化
一.初识Currying柯里化 柯里化(Currying)技术 Christopher Strachey 以逻辑学家 Haskell Curry 命名的(尽管它是 Moses Schnfinkel ...
- Scala 学习之路(十)—— 函数 & 闭包 & 柯里化
一.函数 1.1 函数与方法 Scala中函数与方法的区别非常小,如果函数作为某个对象的成员,这样的函数被称为方法,否则就是一个正常的函数. // 定义方法 def multi1(x:Int) = { ...
- Scala 系列(十)—— 函数 & 闭包 & 柯里化
一.函数 1.1 函数与方法 Scala 中函数与方法的区别非常小,如果函数作为某个对象的成员,这样的函数被称为方法,否则就是一个正常的函数. // 定义方法 def multi1(x:Int) = ...
- 理解运用JS的闭包、高阶函数、柯里化
JS的闭包,是一个谈论得比较多的话题了,不过细细想来,有些人还是理不清闭包的概念定义以及相关的特性. 这里就整理一些,做个总结. 一.闭包 1. 闭包的概念 闭包与执行上下文.环境.作用域息息相关 执 ...
- JS的闭包、高阶函数、柯里化
本文原链接:https://cloud.tencent.com/developer/article/1326958 https://cloud.tencent.com/developer/articl ...
- 【 js 基础 】【 源码学习 】柯里化和箭头函数
最近在看 redux 的源码,代码结构很简单,主要就是6个文件,其中 index.js 负责将剩余5个文件中定义的方法 export 出来,其他5个文件各自负责一个方法的实现. 大部分代码比较简单,很 ...
- 浅析 JavaScript 中的 函数 currying 柯里化
原文:浅析 JavaScript 中的 函数 currying 柯里化 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字 ...
- JS 柯里化 (curry)
用 JS 理解柯里化 函数式编程风格,试图以函数作为参数传递(回调)和无副作用的返回函数(修改程序的状态). 很多语言采用了这种编程风格.JavaScript,Haskell,Clojure,Erla ...
- Scala学习二十一——隐式转换和隐式参数
一.本章要点 隐式转换用于类型之间的转换 必须引入隐式转换,并确保它们可以以单个标识符的形式出现在当前作用域 隐式参数列表会要求指定类型的对象.它们可以从当前作用域中以单个标识符定义的隐式对象的获取, ...
- JavaScript中的柯里化
转载自:https://www.cnblogs.com/zztt/p/4142891.html 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Ha ...
随机推荐
- bat命令1
echo 命令 打开回显或关闭请求回显功能,或显示消息.如果没有任何参数,echo命令将显示当前回显设置. 语法 echo [{on|off}] [message] Sample:@echo off ...
- functool.wraps and functools.partial
functools.partial 通过包装手法,允许我们 "重新定义" 函数签名. 通常是将函数的部分参数给固定下来, 从而形成一个输入参数更少的新函数. functool.w ...
- 13 Stream Processing Patterns for building Streaming and Realtime Applications
原文:https://iwringer.wordpress.com/2015/08/03/patterns-for-streaming-realtime-analytics/ Introduction ...
- 几个开源ssg 技术方案
1. Nanoc 2. Middle Man App 3. Hexo 4. DocPad 5. Hugo 6. Jekyll 7. Octopress 8. Harp ...
- php替换 json符号
- CDN初学搭建(ats)
CDN初学搭建(ats) ats trafficserver squid 一. CDN初学搭建 准备vagrant virtualbox 内部环境测试所需包 一.vagrant创建启动虚拟机 1 mk ...
- Redis简单介绍与安装
Redis是一个开源,高级的键值存储和一个适用的解决方案,用于构建高性能,可扩展的Web应用程序. Redis有三个主要特点,使它优越于其它键值数据存储系统 - 1) Redis将其数据库完全保存在内 ...
- java 工作流
BPM是jboss旗下遵守LGPL许可的java开源工作流,功能比较完善,从4.0开始引入了pvm的概念,支持jPDL.BPEL等流程定义语言.由于相关资料还比较少,开发自己的一个demo还不是太容易 ...
- Linux 制作补丁 打补丁 撤销补丁
1.制作补丁 diff - 逐行比较文件 格式 diff 参数 旧文件/旧文件夹 新文件/新文件夹 -N 将不存在的文件看作是空的 -a 将所有文件都视为文本文件 -u 以合并 ...
- 关于不同应用程序存储IO类型的描述
介绍 存储系统作为数据的载体,为前端的服务器和应用程序提供读写服务.存储阵列某种意义上来说,是对应用服务器提供数据服务的后端“服务器”.应用服务器对存 储系统发送数据的“读”和“写”的请求.然而,不同 ...