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 ...
随机推荐
- 最短路径问题的Dijkstra算法
问题 最短路径问题的Dijkstra算法 是由荷兰计算机科学家艾兹赫尔·戴克斯特拉提出.迪科斯彻算法使用了广度优先搜索解决非负权有向图的单源最短路径问题,算法终于得到一个最短路径树> ...
- MIT App Inventor使用与入门教程
前言:随着信息技术新课标的提出,移动app应用设计被加入到新课标,程序与算法得到体现,学生的创造性,计算思维与信息意识也可以在其中得到体现. 安卓app开发目前比较火热的是Eclipse和Androi ...
- Snippet取表字段说明和详细信息
IF OBJECT_ID (N'dbo.GetDetails', N'IF') IS NOT NULL DROP FUNCTION dbo.GetDetails; GO create function ...
- java代码------计算器核心位置添加
总结:点击等号时,什么代码 else if(str.equals("-")){ ready=true; if(c=='\0'){ num1=Double.parseDouble(j ...
- python实战——文本挖掘+xgboost预测+数据处理+准确度计算整合版
if __name__=="__main__": '''============================先导入数据============================= ...
- spring cache之自定义keys的过期时间
spring @cacheable注解默认不支持方法级别的缓存失效时间,只能通过配置来配置全局的失效时间 如果需要实现对方法级别的缓存支持失效时间机制,有一种比较简单的方法,spring配置文件如下: ...
- 第三章 k8s cluster环境创建
1 用如下方法安装指定版本的docker,但是我的环境会报错 # 安装rpm apt install rpm # 下载 RPM 包, docker 版本 wget https://download. ...
- 十六 在沉睡中停止(在sleep() 状态下停止线程)
1 如果线程在sleep()状态下停止线程,会是什么效果? 答案: 如果在sleep状态下停止某一线程,会进入sleep的catch块中, 抛出InterruptedException 异常,并且清除 ...
- Ubuntu16下编译linux内核,报"mkimage" command not found错的解决
"mkimage" command not found - U-Boot images will not be built /work/system/linux-3.4.20/ar ...
- ALSA声卡笔记3--ASoC驱动重要结构体关系图
1.ASoC中重要的数据结构之间的关联方式 (1)Kernel-2.6.35-ASoC中各个结构的静态关系 ASoC把声卡实现为一个Platform Device,然后利用Platform_devic ...