2

Scala - 隐式转换

 3 years ago
source link: https://segmentfault.com/a/1190000040011455
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Scala - 隐式转换

有时候我们看scala代码的时候,会发现明明没有这个类的类型或者函数,甚至是没有这个类,编译器不仅没有报错,程序还可以正常运行,其实这里就用到了scala的隐式转换。

当我们调用一个对象的方法的时候,但是这个对象并没有这个方法,此时就会触发隐式转换,会把这个对象偷偷的转换为具有这个方法的对象。
比如下面的例子,小鸡可以走路也可以跑,但是它也想像小鸟一样飞,但是它有没有这个功能。我们可以在不对小鸡整改的基础上,引入ChickenImplicit,让小鸡可以隐式的调用Bird的fly方法,让它可以像小鸟一样飞。

object ImplicitDemo1 {
  def main(args: Array[String]): Unit = {
    import ChickenImplicit._
    val chicken = new Chicken()
    chicken.work()
    chicken.run()
    // 隐式转为Bird,并调用Bird的fly方法
    chicken.fly()
  }
}

class Chicken() {
  def work(): Unit = {
    println("小鸡在走")
  }

  def run(): Unit = {
    println("小鸡在跑")
  }
}

class Bird {
  def fly(): Unit = {
    println("小鸟在飞")
  }
}

object ChickenImplicit {
  implicit def chicken2Bird(c: Chicken): Bird = new Bird()
}

上面是额外的定义ChickenImplicit,但是有时候我们可以直接在同一个类里定义,这样局不用加import,具体用哪种还是要看实际场景。

object ImplicitDemo2 {
  def main(args: Array[String]): Unit = {
    val chicken = new Chicken2()
    chicken.work()
    chicken.run()
    // 隐式转为Bird,并调用Bird的fly方法
    chicken.fly()
  }

  implicit def chicken2Bird(c: Chicken2): Bird2 = new Bird2()
}

class Chicken2() {
  def work(): Unit = {
    println("小鸡在走")
  }

  def run(): Unit = {
    println("小鸡在跑")
  }
}

class Bird2 {
  def fly(): Unit = {
    println("小鸟在飞")
  }
}

比如我们要调用方法,打印我们传递的参数,我们是这样写的:

def main(args: Array[String]): Unit = {
    printInfo1("aaa") // aaa
}

def printInfo1(str: String): Unit = {
    println(str)
}

如果我们调用方法的时候,如果不想传递参数,我们可以这样:
在方法里指定默认值

def main(args: Array[String]): Unit = {
    printInfo2("bbb") // bbb
    printInfo2() // default
}

def printInfo2(str: String = "default"): Unit = {
    println(str)
}

如果通过隐式参数,那我们就可以这样:
这里的方法不加括号也是可以的。由于是通过类型来匹配隐式值的,所以在一个作用域中,同一个类型只能有一次,并且他的优先级高于默认的,所以没有传递参数的时候,打印的implicit。

def main(args: Array[String]): Unit = {
    implicit val str: String = "implicit"
    printInfo3("ccc") // ccc
    printInfo3() // default
    printInfo3 // implicit
}

def printInfo3(implicit str: String = "default"): Unit = {
    println(str)
}

当我们需要隐式转换的时候,我们就需要用implicit关键字。
隐式转换的时候,他会先全局的查找是否有匹配的方法或者参数,如果没有再考虑隐式转换。
由于隐式参数是根据类型的,所以同一作用域不能定义多个同一个类型的,并且默认值是优先于默认的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK