scala成长之路(3)隐式转换

不废话,先上例子:定义一个参数类型为String的函数:

scala> def sayHello(name:String) = println("hello " + name)
sayHello: (name: String)Unit

然后调用此函数,但传入参数为1,可想而知一定会报错:

scala> sayHello(1)
<console>:13: error: type mismatch;
found : Int(1)
required: String
sayHello(1)

很简单,因为函数要求的参数类型为String,而传入类型为Int,类型不匹配。但是,如果此时定义一个隐式类型转换函数,指明原参数类型和转换后的参数类型,函数名随意╮(╯▽╰)╭:

scala> implicit def hahahaa(s:Int):String = s.toString
<console>:11: warning: implicit conversion method hahahaa should be enabled
by making the implicit value scala.language.implicitConversions visible.
This can be achieved by adding the import clause 'import scala.language.implicitConversions'
or by setting the compiler option -language:implicitConversions.
See the Scaladoc for value scala.language.implicitConversions for a discussion
why the feature should be explicitly enabled.
implicit def hahahaa(s:Int):String = s.toString

虽然报了一大堆警告,但是可以看出来定义成功了。(警告可以通过import scala.language.implicitConversions来消除)

此时再调用

scala> sayHello(1)
hello 1

可以看到调用成功,事实上此类函数时,一般会先根据传入参数类型和要求参数类型寻找相应的隐式转换函数,将转换函数的执行结果作为输入。

回归正题,scala的隐式转换有3中应用场景:

1. 即上边的参数转换场景:当传入的参数与定义的参数类型不匹配,则在当前作用域内寻找对应的隐式转换函数;

2. 参数值隐式传入场景:当函数中有定义隐式参数时(需单独列出来),会在当前作用域寻找同类型的隐式变量/标量,直接传入,无需在调用时传入:

scala> def sayHi(name:String)(implicit words:String) = print("Hi,"+name+"!"+words)
sayHi: (name: String)(implicit words: String)Unit

scala> implicit val w = "nice to meet you!"
w: String = nice to meet you!
scala
> sayHi("zhangsan") Hi,zhangsan!nice to meet you!

其实相当于定制化的函数内变量初始化。需要注意,在这里不能有两个相同类型的隐式值,否则出错。

3. 增强功能型隐式转换:很容易理解,在A类对象上调用B类对象独有方法,肯定报错;但是如果定义了从A类到B类的隐式转换函数,那么久能行通了,先通过转换函数转换后再调用:

ImplicitTest.scala:

package basic{
    package test{
        class Dog(n:String){
            val name = n
            def bark = print("wang,wang,wang...")
            val dogNum = System.nanoTime
        }
        class Person(n:String){
            val name = n
            def talk = print("Hello, nice to meet you.")
        }
    }
}

run.scala

import basic.test._

var liuqing = new Person("Liuqing")
implicit def doBadThings(p:Person) = {
    new Dog(p.name + "_dog")
}
a.bark

执行结果:

D:\workspace\scala\test>scala run.scala
warning: there was one feature warning; re-run with -feature for details
one warning found
wang,wang,wang...

你看,柳青可以学狗叫了^^

但是要注意,这里的隐式转换只在方法调用时能触发,在public成员访问时不能触发,即,这里调用liuqing.dogNum,并不会触发转换,会报错。

猜你喜欢

转载自www.cnblogs.com/wangyalou/p/9568213.html
今日推荐