Scala(五) 隐式转换

一:简介

隐式转换使用关键字implicit来修饰,隐式转换的命名方式是"源数据类型2目标数据类型",隐式转换的作用是自动的将源数据类型转为目标数据类型。

隐式转换可用于函数和值

二:示例

示例1

class Foo(var name: String)

class Bar(var name: String)

class Foobar(var name: String)

class Foobaz {
  def test(foobar: Foobar): Unit = {
    println("test")
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    // 注意:Foo、Bar、Foobar 三个类时独立的没有任何关系
    var foo = new Foo("foo")
    var baz = new Bar("bar")
    var foobaz = new Foobaz

    // test(foobar: Foobar) test方法接收的参数类型为Foobar类型,这里传的是Foo类型,编译器不报错
    // 不报错的原因是Scala会检查有没有一种函数名叫foo2Foobar的,没有找到但是找到了any2Foobar也是满足条件的
    // 就自动将传递的参数转化为Foobar类型
    foobaz.test(foo)
  }

  // 隐式转换:转换是隐式的,怎么转换是自己显式的定义出来的
  implicit def any2Foobar(any: Any): Foobar = {
    if (any.isInstanceOf[Foo]) {
      val foo = any.asInstanceOf[Foo]
      new Foobar(foo.name)
    } else if (any.isInstanceOf[Bar]) {
      val bar = any.asInstanceOf[Bar]
      new Foobar(bar.name)
    } else {
      null
    }
  }
}

全局implicit object类

class Foo(var name: String)

class Bar(var name: String)

class Foobar(var name: String)

class Foobaz {
  def test(foobar: Foobar): Unit = {
    println("test")
  }
}

object Main333 {
  def main(args: Array[String]): Unit = {
    val foo = new Foo("foo")
    val baz = new Bar("bar")
    val foobaz = new Foobaz

    import ImplicitUtil.any2Foobar
    foobaz.test(foo)
  }
}

// 可将需要隐式转换的函数或者变量封装到一个全局的object类中,在使用的时候通过import导入进来即可
object ImplicitUtil {
  implicit def any2Foobar(any: Any): Foobar = {
    if (any.isInstanceOf[Foo]) {
      val foo = any.asInstanceOf[Foo]
      new Foobar(foo.name)
    } else if (any.isInstanceOf[Bar]) {
      val bar = any.asInstanceOf[Bar]
      new Foobar(bar.name)
    } else {
      null
    }
  }
}

示例2

class HtmlString(var str: String) {
  def sout(): Unit = {
    println("<H1>" + str + "</H1>")
  }
}

object Main {

  // 将String自动转换为HtmlString类型
  implicit def stringToBase(str: String): HtmlString = new HtmlString(str)

  def main(args: Array[String]): Unit = {
    val string = "Hello"
    // String并没有sout方法,而是将String转为HtmlString, 此时相当于String继承了HtmlString,可以调用任意公有的方法
    // 这种用法用于对类的增强,让一个类具有另一个类的方法而不用去继承
    string.sout()
  }
}

隐式参数

class Foo {
  def sout(value: String): Unit = {
    println(value)
  }
}

object Main {
  // 定义了两个参数:被implicit修饰的参数称之为隐式参数
  def test(name: String)(implicit foo: Foo): Unit = {
    foo.sout(name)
  }

  def main(args: Array[String]): Unit = {
    implicit val foo = new Foo
    // 隐式参数不需要显式传值,系统会将使用implicit修饰的变量作为参数传递过去
    test("mengday")
  }
}
发布了308 篇原创文章 · 获赞 936 · 访问量 133万+

猜你喜欢

转载自blog.csdn.net/vbirdbest/article/details/88918822