隐式转换
它是scala的一种特殊的功能,它能将一种数据类型转换为另一种数据类型,然后这种数据类型将拥有另一种数据类型的所有方法。可以看成对类的增强。
隐式转换分为两种:
1)隐式转换函数
2)隐式转换值
隐式转换的关键字 implicit
隐式转换命名方式 one2one
/*特殊人群*/
class SpecialPerson01(var name: String)
/*老人*/
class Older01(var name: String)
/*成年人*/
class Adult01(var name: String)
object ImplicitDemo01 {
/*此方法是用来买特殊票的窗口*/
def buySpeciaTicketlWindow(p: SpecialPerson01): Unit = {
if (p != null) {
println(p.name + "购买了一张特殊票!")
} else {
println("您不是特殊人群,请去正常窗口购票!")
}
}
/*此方法的作用就是将 Order01或者Children01类型转为SpecialPerson01类型*/
implicit def any2SpecialPerson01(any: Any):SpecialPerson01 = {
if(any.isInstanceOf[Older01]) {
val older01 = any.asInstanceOf[Older01]
new SpecialPerson01(older01.name)
}
else{
null
}
}
def main(args: Array[String]): Unit = {
val special = new SpecialPerson01("特殊人")
val older01 = new Older01("老人")
val adult = new Adult01("成年人")
// buySpeciaTicketlWindow(special)
// buySpeciaTicketlWindow(order) 无法将order对象作为buySpeciaTicketlWindow参数 类型不匹配
/**
* 那么如何将 order和 children转为特殊人群呢?
* 我们定义一个隐式转换函数然后可以使用隐式转换函数*/
/**
* 这里我们给buySpeciaTicketlWindow 传入的参数是Order01类型 为什么能够可以了呢?
* 在scala中 它会自动去查找程序中会不会存在implicit关键字将 Order01类型转为SpecialPerson01类型
* 如果存在那么将Order01自动的隐式转换为SpecialPerson01
**/
buySpeciaTicketlWindow(older01)
buySpeciaTicketlWindow(adult)
}
}
隐式转换对类的增强
class RichFile(var file: File) { def read(): Unit = { val content = Source.fromFile(file).mkString println(content) } } /*隐式转换对类的增强*/ class ImplicitDemo02 { } object ImplicitDemo02 { def main(args: Array[String]): Unit = { var file = new File("D:\\tmp\\h2o-28160\\h2ologs\\h2o_127.0.0.1_54321-4-warn") /** file想调用 RichFile类中的read方法 是无法调用的 */ // file.read() /** 为了能够让 file能够调用 RichFile类中的read方法 可以将file隐式转换为RichFile */ file.read()//scala在程序中自动的查找看是否有隐式转换 将File转为RichFile implicit def file2RichFile(file: File): RichFile = { new RichFile(file) } } }
隐式参数
scala方法中的参数被 implicit 关键字修饰那么这个参数就是隐式参数。
使用隐式参数,避免了的调用方法的时候每次传入相同的类型问题。
class SinPen {
def write(content: String): Unit = {
println(content)
}
}
class ImplicitDemo03 {
}
object ImplicitDemo03 {
def main(args: Array[String]): Unit = {
// 每次调用sinForExam方法时候都会传入SinPen对象 我们可以使用隐式参数 避免这个问题
val p = new SinPen
sinForExam("ysj")(p)
sinForExam("qff")(p)
/*隐式参数的使用*/
implicit val p2 = new SinPen
sinForExam("spark")
sinForExam("hive")
}
def sinForExam(name: String)(implicit p: SinPen): Unit = {
p.write(name)
}
}
扩大隐式转换作用域
以前书写隐式转换函数或者隐式转换值都是在本类中定义的,这样就会存在着局限性。为了避免这个局限性可以将隐式转换函数和隐式转换值定义在object对象中这样就可以扩大隐式转换的作用域,以后多个地方使用的话,我们直接使用import将对应的隐式转换函数或者值导入即可。
视图界定
/*视图界定 * 使用符号 <% T<% Person 表示T只能是Person的子类 或者T能隐式转换成Person*/ class Person05(var name: String) { def sayHello() = { println("I am " + name) } def makeFriends(p: Person05): Unit = { sayHello() p.sayHello() } } class student05(name: String) extends Person05(name) class Cat(var name: String) { def sayHello(): Unit = { println("miao miao is " + name) } } /*泛型T只能是Person05及其子类,或者T能够隐式转换成Person05类型*/ class Party[T <% Person05](p1: T, p2: T) { p1.makeFriends(p2) } object ImplicitDemo05 { def main(args: Array[String]): Unit = { /*T 是Person05的情形*/ val p1 = new Person05("xiaoming") val p2 = new Person05("baby") val pty = new Party[Person05](p1, p2) /*T 是Person05子类的情形*/ val s1 = new student05("ysj") val s2 = new student05("qff") val pty2 = new Party[student05](s1, s2) /**T是 Cat的情形 会报错 因为Cat 不是Person05类型以及Person05的子类 * 但是我们可以将Cat隐式转换为Person05*/ /* val c1 = new Cat("ysj") val c2 = new Cat("qff") val pty3 = new Party[Cat](c1, c2)*/ implicit def cat2Person05(cat:Cat):Person05={ new Person05(cat.name) } val c1 = new Cat("cat1") val c2 = new Cat("cat2") val pty3 = new Party[Cat](c1, c2) } }