博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Scala Essentials: 隐式转换
阅读量:6455 次
发布时间:2019-06-23

本文共 4376 字,大约阅读时间需要 14 分钟。

Class Extension

"+9519760513".exists(_.isDigit)

java.lang.String并存在exists方法,为此标准库中在Predef定义了一个隐式转换,使String隐式地转换为StringOps,从而提供更多地操作字符串的方法。

object Predef {  implicit def augmentString(x: String): StringOps = new StringOps(x)}

Implicit Resolution Rules

Marking Rule

Only definitions marked implicit are available.

object Predef {  implicit def intWrapper(x: Int) = new scala.runtime.RichInt(x)}
object Predef {  implicit final class any2stringadd[A](private val self: A) extends AnyVal {    def +(other: String): String = String.valueOf(self) + other  }}

Scope Rule

An inserted implicit conversion must be in scope as a single identifier, or be associated with the source or target type of the conversion.

case class Yard(val amount: Int)case class Mile(val amount: Int)

mile2yard可以定义在object Mile

object Mile {  implicit def mile2yard(mile: Mile) = new Yard(10*mile.amount)}

也可以定义在object Yard

object Yard {  implicit def mile2yard(mile: Mile) = new Yard(10*mile.amount)}

转换为目标类型时,常常发生如下两个场景:

  • 传递参数时,但类型匹配失败;

def accept(yard: Yard) = println(yard.amount + " yards")accept(Mile(10))
  • 赋值表达式,但类型匹配失败

val yard: Yard = Mile(10)

Other Rules

  • One-at-a-time Rule: Only one implicit is tried.

  • Explicits-First Rule: Whenever code type checks as it is written, no implicits are attempted.

  • No-Ambiguty Rule: An implicit conversion is only inserted if there is no other possible conversion is inserted.

Where implicits are tried?

  • Conversions to an expected type

    • 传递参数时,但类型匹配失败;

    • 赋值表达式,但类型匹配失败

  • Conversions of the receiver of a selection

    • 调用方法,方法不存在

    • 调用方法,方法存在,但参数类型匹配失败

  • Implicit parameters

Implicit parameters

import scala.math.Orderingcase class Pair[T](first: T, second: T){  def smaller(implicit order: Ordering[T]) =    order.min(first, second)}

TInt

Pair(1, 2).smaller

编译器实际调用:

Pair(1, 2).smaller(Ordering.Int)

其中Ordering.Int定义在Ordering的伴生对象中

object Ordering {  trait IntOrdering extends Ordering[Int] {    def compare(x: Int, y: Int) =      if (x < y) -1      else if (x == y) 0      else 1  }  implicit object Int extends IntOrdering}

也就是说

implicitly[Ordering[Int]] == Ordering.Int  // true

其中,implicitly为定义在Predef的一个工具函数,用于提取隐式值

@inline def implicitly[T](implicit e: T) = e

T为自定义类型

import scala.math.Orderingcase class Point(x: Int, y: Int)object Point {  implicit object OrderingPoint extends Ordering[Point] {    def compare(lhs: Point, rhs: Point): Int =      (lhs.x + lhs.y) - (rhs.x + rhs.y)  }}
Pair(Point(0, 0), Point(1, 1)).smaller

等价于

Pair(Point(0, 0), Point(1, 1)).smaller(Point.OrderingPoint)

也就是说

implicitly[Ordering[Point]] == Point.OrderingPoint

Context Bound

import scala.math.Orderingcase class Pair[T : Ordering](first: T, second: T) {  def smaller(implicit order: Ordering[T]) = order.min(first, second)}

可以使用implicitly简化

import scala.math.Orderingcase class Pair[T : Ordering](first: T, second: T) {  def smaller = implicitly[Ordering[T]].min(first, second)}

可以进一步简化

import scala.math.Orderingcase class Pair[T : Ordering](first: T, second: T) {  def smaller = Ordering[T].min(first, second)}

Ordering[T]首先调用了object Orderingapply方法,从而便捷地找到了Order[T]的隐式值

object Ordering {  def apply[T](implicit ord: Ordering[T]) = ord}

所以Ordering[T].min等价于implicitly[Ordering[T]].min

View Bound

import scala.math.Orderedcase class Pair[T](first: T, second: T){  def smaller(implicit order: T => Ordered[T]) = {    if (order(first) < second) first else second  }}

implicit order: T => Ordered[T]smaller的局部作用域内,即是一个隐式参数,又是一个隐式转换函数

import scala.math.Orderedcase class Pair[T](first: T, second: T){  def smaller(implicit order: T => Ordered[T]) = {    if (first < second) first else second  }}

又因为在Predef预定义了从IntRichInt的隐式转换,而RichIntOrdered[Int]的子类型,所以在Predef定义的implicit Int => RichInt的隐式转换函数可作为隐式参数implicit order: T => Ordered[T]的隐式值。

Pair(1, 2).smaller

等价于

Pair(1, 2).smaller(Predef.intWrapper _)

上述简化的设计,使得隐式参数order没有必要存在,这样的模式较为常见,可归一为一般模式:View Bound

import scala.math.Orderedcase class Pair[T <% Ordered[T]](first: T, second: T) {  def smaller = if (first < second) first else second}

需要注意的是:T <% Ordered[T]表示:T可以隐式转换为Ordered[T];而T <: Ordered[T]表示:TOrdered[T]的一个子类型。

Upper Bound

import scala.math.Orderedcase class Pair[T <: Comparable[T]](first: T, second: T) {  def smaller = if (first.compareTo(second) < 0) first else second}
Pair("1", "2").smaller  // OK, String is subtype of Comparable[String]Pair(1, 2).smaller      // Compile Error, Int is not subtype of Comparable[Int]

转载地址:http://qhfzo.baihongyu.com/

你可能感兴趣的文章
Ubuntu14更换源
查看>>
IE9下不显示select
查看>>
day24-组合搜索组件
查看>>
Swagger-UI报Unable to infer base url
查看>>
gcc/g++ 实战之编译的四个过程
查看>>
InnoDB杂记
查看>>
【PHP基础】PHP与Web页面交互(表单处理)
查看>>
能用条件注释改善的IE兼容问题
查看>>
UVA 10692 Huge Mods(指数循环节)
查看>>
awardactivity/classfragment
查看>>
WPF and Silverlight 学习笔记(二十五):使用CollectionView实现对绑定数据的排序、筛选、分组...
查看>>
Linux Shell多命令执行
查看>>
【递推】月落乌啼算钱
查看>>
RCC BUCK变压器设计
查看>>
DAO层,Service层,Controller层、View层
查看>>
LeetCode刷题系列——Add Two Numbers
查看>>
python3.4.3 调用http接口 解析response xml后插入数据库
查看>>
使用VS2008,VS2010编译64位的应用程序
查看>>
关于java Integer大小比较的问题
查看>>
C++创建学生类练习
查看>>