千家信息网

Scala系列之隐式转换和隐式参数

发表于:2024-11-19 作者:千家信息网编辑
千家信息网最后更新 2024年11月19日,Scala系列之隐式转换和隐式参数5.1. 概念隐式转换和隐式参数是Scala中两个非常强大的功能,利用隐式转换和隐式参数,你可以提供优雅的类库,对类库的使用者隐匿掉那些枯燥乏味的细节。5.2. 作用
千家信息网最后更新 2024年11月19日Scala系列之隐式转换和隐式参数

Scala系列之隐式转换和隐式参数
5.1. 概念
隐式转换和隐式参数是Scala中两个非常强大的功能,利用隐式转换和隐式参数,你可以提供优雅的类库,对类库的使用者隐匿掉那些枯燥乏味的细节。

5.2. 作用
隐式的对类的方法进行增强,丰富现有类库的功能

object ImplicitDemo extends App{
//定义隐式类,可以把File转换成定义的隐式类RichFile
implicit class RichFile(from:File){
def read:String = Source.fromFile(from.getPath).mkString
}
//使用隐式类做已有类的动能的扩展
val contents = new File("src/test1.txt").read
println(contents)

}

5.5. 隐式类
创建隐式类时,只需要在对应的类前加上implicit关键字。比如:

object Helpers {
implicit class IntWithTimes(x: Int) {
def times[A](f: => A): Unit = {
def loop(current: Int): Unit =
if(current > 0) {
f
loop(current - 1)
}
loop(x)
}
}
}

这个例子创建了一个名为IntWithTimes的隐式类。这个类包含一个int值和一个名为times的方法。要使用这个类,只需将其导入作用域内并调用times方法。比如:

scala> import Helpers.
import Helpers.

scala> 5 times println("HI")
HI
HI
HI
HI
HI

使用隐式类时,类名必须在当前作用域内可见且无歧义,这一要求与隐式值等其他隐式类型转换方式类似。

只能在别的trait/类/对象内部定义。

object Helpers {   implicit class RichInt(x: Int) // 正确!}implicit class RichDouble(x: Double) // 错误!

构造函数只能携带一个非隐式参数。

implicit class RichDate(date: java.util.Date) // 正确!
implicit class Indexer[T](collecton: Seq[T], index: Int) // 错误!
implicit class Indexer[T](collecton: Seq[T])(implicit index: Index) // 正确!

虽然我们可以创建带有多个非隐式参数的隐式类,但这些类无法用于隐式转换。

在同一作用域内,不能有任何方法、成员或对象与隐式类同名。

object Bar
implicit class Bar(x: Int) // 错误!

val x = 5
implicit class x(y: Int) // 错误!

implicit case class Baz(x: Int) // 错误!

5.6. 隐式转换函数
是指那种以implicit关键字声明的带有单个参数的函数,这种函数将被自动引用,将值从一种类型转换成另一种类型。

使用隐含转换将变量转换成预期的类型是编译器最先使用 implicit 的地方。这个规则非常简单,当编译器看到类型X而却需要类型Y,它就在当前作用域查找是否定义了从类型X到类型Y的隐式定义。

比如,通常情况下,双精度实数不能直接当整数使用,因为会损失精度:

scala> val i:Int = 3.5
:7: error: type mismatch;
found : Double(3.5)
required: Int
val i:Int = 3.5
^

当然你可以直接调用 3.5.toInt。

这里我们定义一个从 Double 到 Int 的隐含类型转换的定义,然后再把 3.5 赋值给整数,就不会报错。

scala> implicit def doubleToInt(x:Double) = x toInt
doubleToInt: (x: Double)Int
scala> val i:Int = 3.5
i: Int = 3

此时编译器看到一个浮点数 3.5,而当前赋值语句需要一个整数,此时按照一般情况,编译器会报错,但在报错之前,编译器会搜寻是否定义了从 Double 到 Int 的隐含类型转换,本例,它找到了一个 doubleToInt。 因此编译器将把

val i:Int = 3.5

转换成

val i:Int = doubleToInt(3.5)

这就是一个隐含转换的例子,但是从浮点数自动转换成整数并不是一个好的例子,因为会损失精度。 Scala 在需要时会自动把整数转换成双精度实数,这是因为在 Scala.Predef 对象中定义了一个

implicit def int2double(x:Int) :Double = x.toDouble

而 Scala.Predef 是自动引入到当前作用域的,因此编译器在需要时会自动把整数转换成 Double 类型。

5.7. 隐式参数
object Test{
trait Adder[T] {
def add(x:T,y:T):T
}

implicit val a = new Adder[Int] {  override def add(x: Int, y: Int): Int = x+y}def addTest(x:Int,y:Int)(implicit adder: Adder[Int]) = {  adder.add(x,y)}

addTest(1,2) // 正确, = 3
addTest(1,2)(a) // 正确, = 3
addTest(1,2)(new Adder[Int] {
override def add(x: Int, y: Int): Int = x-y
}) // 同样正确, = -1
}

类型 参数 编译器 编译 作用 整数 错误 函数 方法 精度 例子 对象 关键 关键字 功能 实数 情况 损失 点数 强大 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器怎么通过网线配置 女生做软件开发难找工作吗 软件开发项目形象进度 惠普服务器售后400电话 国家网络安全研究中心怎么样 软件开发账务处理流程 上海动萌网络技术有限公司 甘肃省教育厅中小学网络安全 手机遥控空调软件开发 大数据数据库工程师培训机构 考勤机数据库如何导入管理系统 专业网络安全培训方案 数据库连接获取阻塞 员工内训软件开发价钱 阿里云网络服务器安全等级 工商部门市场主体数据库 网络安全小 百讯网络技术有限公司 企业网络安全搭建论文 山东华为服务器虚拟化技术云主机 4月关于网络安全的宣传 性能测试工资与软件开发 狼人杀游戏登录服务器超时怎么办 趣话网络安全传输协议 用jdbc增加数据库 梦幻服务器ip 腾讯云服务器学生套餐 北京web前端软件开发怎么样 网络安全微网文题目 武汉自助点餐机软件开发
0