`
zhaomengsen
  • 浏览: 207684 次
  • 性别: Icon_minigender_1
  • 来自: 河北
社区版块
存档分类
最新评论

Scala implicit

 
阅读更多
Scala implicit
implicit基本含义
在Scala中有一个关键字是implicit, 之前一直不知道这个货是干什么的,今天整理了一下。

我们先来看一个例子:

def display(input:String):Unit = println(input)我们可以看到,display函数的定义只是接受String类型的入参,因此调用display("any string")这样的函数是没问题的。但是如果调用display(1)这样的入参不是String类型的话,编译会出错的。

如果我们想让display函数也能够支持Int类型的入参的话,除了我们重新定一个def display(input:Int):Unit = println(input)这样的函数以外,我们还可以在相同的作用域内用implicit关键字定义一个隐式转换函数,示例代码如下:

object ImplicitDemo {

  def display(input:String):Unit = println(input)

  implicit def typeConvertor(input:Int):String = input.toString

  implicit def typeConvertor(input:Boolean):String = if(input) "true" else "false"

//  implicit def booleanTypeConvertor(input:Boolean):String = if(input) "true" else "false"


  def main(args: Array[String]): Unit = {
    display("1212")
    display(12)
    display(true)
  }

}我们定义了2个隐式转换函数:

  implicit def typeConvertor(input:Int):String = input.toString

  implicit def typeConvertor(input:Boolean):String = if(input) "true" else "false"这样display函数就可以接受String、Int、Boolean类型的入参了。注意到上面我们的例子中注释的那一行,如果去掉注释的那一行的话,会在运行的时候出现二义性:

Error:(18, 13) type mismatch;
found   : Boolean(true)
required: String
Note that implicit conversions are not applicable because they are ambiguous:
both method typeConvertor in object ImplicitDemo of type (input: Boolean)String
and method booleanTypeConvertor in object ImplicitDemo of type (input: Boolean)String
are possible conversion functions from Boolean(true) to String
    display(true)
            ^得出的结论是:

隐式转换函数是指在同一个作用域下面,一个给定输入类型并自动转换为指定返回类型的函数,这个函数和函数名字无关,和入参名字无关,只和入参类型以及返回类型有关。注意是同一个作用域。
implicit的应用
我们可以随便的打开scala函数的一些内置定义,比如我们最常用的map函数中->符号,看起来很像php等语言。
但实际上->确实是一个ArrowAssoc类的方法,它位于scala源码中的Predef.scala中。下面是这个类的定义:

  final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal {
    // `__leftOfArrow` must be a public val to allow inlining. The val
    // used to be called `x`, but now goes by `__leftOfArrow`, as that
    // reduces the chances of a user's writing `foo.__leftOfArrow` and
    // being confused why they get an ambiguous implicit conversion
    // error. (`foo.x` used to produce this error since both
    // any2Ensuring and any2ArrowAssoc pimped an `x` onto everything)
    @deprecated("Use `__leftOfArrow` instead", "2.10.0")
    def x = __leftOfArrow

    @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y)
    def →[B](y: B): Tuple2[A, B] = ->(y)
  }
  @inline implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)我们看到def ->[B] (y :B)返回的其实是一个Tuple2[A,B]类型。
我们定义一个Map:

scala> val mp = Map(1->"game1",2->"game_2")
mp: scala.collection.immutable.Map[Int,String] = Map(1 -> game1, 2 -> game_2)这里 1->"game1"其实是1.->("game_1")的简写。
这里怎么能让整数类型1能有->方法呢。
这里其实any2ArrowAssoc隐式函数起作用了,这里接受的参数[A]是泛型的,所以int也不例外。
调用的是:将整型的1 implicit转换为 ArrowAssoc(1)
看下构造方法,将1当作__leftOfArrow传入。
->方法的真正实现是生产一个Tuple2类型的对象(__leftOfArrow,y ) 等价于(1, "game_id")
这就是一个典型的隐式转换应用。

其它还有很多类似的隐式转换,都在Predef.scala中:
例如:Int,Long,Double都是AnyVal的子类,这三个类型之间没有继承的关系,不能直接相互转换。
在Java里,我们声明Long的时候要在末尾加上一个L,来声明它是long。
但在scala里,我们不需要考虑那么多,只需要:

scala> val l:Long = 10
l: Long = 10这就是implicit函数做到的,这也是scala类型推断的一部分,灵活,简洁。
其实这里调用是:

val l : Long = int2long(10)更牛逼的功能
为现有的类库增加功能的一种方式,用java的话,只能用工具类或者继承的方式来实现,而在scala则还可以采用隐式转化的方式来实现。

隐式参数
看一个例子再说:

object ImplictDemo {

  object Context{
    implicit val ccc:String = "implicit"
  }


  object Param{
    def print(content:String)(implicit prefix:String){
      println(prefix+":"+content)
    }
  }

  def main(args: Array[String]) {
    Param.print("jack")("hello")

    import Context._
    Param.print("jack")
  }

}程序运行结果为:

hello:jack
implicit:jack隐式转换扩展
import java.io.File

import scala.io.Source

class RichFile(val file:File){
  def read = Source.fromFile(file.getPath()).mkString
}

object Context{
  implicit def file2RichFile(f:File)= new RichFile(f)
}

object ImplictDemo {

  def main(args: Array[String]) {
    import Context.file2RichFile
    println(new File("f:\\create.sql").read)
  }

}上面的代码中调用的read方法其实就是RichFile中定义的read方法。

最后的总结:

1.记住隐式转换函数的同一个scop中不能存在参数和返回值完全相同的2个implicit函数。
2.隐式转换函数只在意 输入类型,返回类型。
3.隐式转换是scala的语法灵活和简洁的重要组成部分
参考资料
•http://blog.csdn.net/oopsoom/article/details/24643869


分享到:
评论

相关推荐

    scala 隐式转换与隐式参数的使用方法

    Scala 隐式转换与隐式参数的使用方法 Scala 中的隐式转换与隐式参数是两个非常重要的概念,它们可以帮助开发者编写更加简洁、灵活和可维护的代码。本文将详细介绍 Scala 中隐式转换与隐式参数的使用方法,并通过...

    scala高级特性

    Scala 高级特性 Scala 是一个多-paradigm programming language,它结合了面向对象和函数式编程的特性。在这个主题中,我们将深入探讨 Scala 的高级特性,包括高阶函数和隐式转换。 高阶函数 高阶函数是 Scala ...

    Scala - Implicit Conversion.docx

    在Scala编程语言中,隐式转换(Implicit Conversion)是一种强大的特性,它允许我们不显式地将一个类型的值转换为另一个类型。隐式转换在某些特定情况下非常有用,例如当两个不兼容的类型需要一起工作时,或者为了...

    Scala 专题教程 - 隐式变换和隐式参数-内含源码以及设计说明书(可以自己运行复现).zip

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性。在Scala中,隐式变换和隐式参数是两个重要的高级特性,它们极大地提升了代码的简洁性和可读性。本教程将深入探讨这两个概念,并通过源码实例...

    Scala Cookbook

    - **隐式转换**:通过`implicit`关键字,可以创建隐式转换,使类型之间的转换更加方便。 - **类型参数**:泛型让代码更具通用性,可以应用于各种数据类型。 ### 6. 并发与Actor模型 - **Actor**:Scala的Akka库...

    scala-form-with-enum:如何在模型类中创建具有枚举类型的表单的示例

    implicit val paintRequestFormat = Json.format[PaintRequest] ``` 现在,我们可以通过`Json.toJson`方法将`PaintRequest`对象转换为JSON: ```scala val request = PaintRequest(Color.Red) val json = Json.to...

    Scala-2.8.1-API.chm.7z

    3. **Implicit Conversions**:隐式转换允许在适当的时候自动将一个类型转换为另一个类型,提高了代码的简洁性,但同时也需要注意滥用可能带来的问题。 4. **Collections Library**:Scala的集合库在2.8.x版本进行了...

    1、scala面试题(25问).pdf

    Scala语言中的隐式转换函数是指那种以implicit关键字申明的带有单个参数的函数,这样的函数会被自动应用,将值从一种类型转换为另一种类型。 7. 伴生类和伴生对象 在Scala语言中,单例对象与类同名时,该对象被...

    A.Beginner's.Guide.to.Scala

    然而,Scala的面向对象编程与传统的OOP语言(例如C++和Java)有所不同,它具有更丰富的语言特性,如特质(trait)、隐式转换(implicit conversion)和case类(case class),这些特性使得Scala的面向对象编程更加...

    函数

    在Scala语言中,函数扮演着至关重要的角色,它支持多种类型的函数定义方式。 函数定义的基本语法如下: ```scala def 函数名(参数名: 参数类型,…): 返回值类型 = { 函数体 } ``` 这里有几个关键点需要注意: 1...

    singleton-ops:基本和字符串单例类型的操作

    implicit class SingletonExt(s: MySingleton.type) { def someMethod(): Unit = println("Method called on singleton") } MySingleton.someMethod() // 使用隐式转换调用方法 ``` 在标题中提到的“字符串单例...

    scala学习笔记

    - **隐式转换**:通过 `implicit` 关键字定义隐式转换规则,可以在编译时自动转换类型。 - **延迟初始化**:使用 `lazy` 关键字定义变量,该变量只在首次使用时计算并存储结果。 - **异常处理**:Scala 提供了丰富的...

    Scala Functional Programming Patterns

    5. 隐式转换(Implicit Conversions):Scala的隐式转换允许将一个类型自动转换为另一个类型,这为库的设计提供了灵活性,允许在不修改现有代码的情况下扩展类型的功能。 《Scala Functional Programming Patterns...

    Scala第十四章节1

    首先,隐式转换(Implicit Conversions)是Scala中的一种高级特性,它允许我们为一个类型定义一个方法,使得当这个类型的对象需要使用该方法时,系统能够自动调用这个转换方法,将其转换为另一种类型。这通常用于...

    Scala-with-cats

    书中进一步探讨了隐式(Implicits)的使用,包括如何打包隐式(Packaging Implicits),隐式的范围(Implicit Scope),以及递归隐式解析(Recursive Implicit Resolution)。隐式是一个非常强大的Scala特性,它允许...

Global site tag (gtag.js) - Google Analytics