我们需要某个类中的一个方法,但是这个类没有提供这样的一个方法,所以我们需要隐式转换,转换成提供了这个方法的类,然后再调用这个方法
需要:A.abc(),但是A类中没有定义abc()方法,需要把A隐式的转化成B,然后在调用.abc()
B.abc()
- 第一步,需要一个增强的类,里面提供我们想要的方法,接收的参数的类型一定要是被增强类的类型。
- 第二部,还需要在单例对象(伴生对象)中写明隐式转换
- 第三步,把隐式转换函数导进来
在spark中隐士转换都写在伴生对象中,因为类的实例肯定能找到伴生对象的,在一个作用域当中
案例:
import scala.io.Source
import java.io.File
//这里的RichFile相当于File的增强类 需要将被增强的类作为参数传入构造器中
class RichFile(val file: File) {
def read = {
Source.fromFile(file.getPath).mkString
}
}
//implicit是隐式转换的关键字 这里定义一个隐式转换函数把当前类型转换成增强的类型
object Context {
//File --> RichFile
implicit def file2RichFile(file: File) = new RichFile(file)
}
object Hello_Implicit_Conversions {
def main(args: Array[String]): Unit = {
//导入隐式转换
import Context.file2RichFile
//File类本身没有read方法 通过隐式转换完成
//这里的read方法是RichFile类中的方法 需要通过隐式转换File --> RichFile
println(new File("E:\\projectTest\\1.txt").read)
val bool: Boolean = new File("E:\\projectTest\\1.txt").exists()
}
}
说明:
File类中没有read方法,RichFile类中有read方法,通过隐式转化,自动把把RichFile中的方法增加到File类中,从而增强File类的功能。
疑问:
1、为什么Context对象是单例对象???是伴生对象????
答:伴生对象首先是一个单例对象,单例对象用关键字object定义。在Scala中,单例对象分为两种,一种是并未自动关联到特定类上的单例对象,称为独立对象 (Standalone Object);
另一种是关联到一个类上的单例对象,该单例对象与该类共有相同名字,则这种单例对象称为伴生对象(Companion Object),对应类称为伴生类。
2、怎么声明两个隐式参数???????
未解决,欢迎大牛来讲解
隐式参数
代码:
object Context_Implicits {
implicit val default: String = "Java"
}
object Param {
//函数中用implicit关键字 定义隐式参数
def print(context: String)(implicit language: String){
println(language+":"+context)
}
}
object Implicit_Parameters {
def main(args: Array[String]): Unit = {
//隐式参数正常是可以传值的,和普通函数传值一样 但是也可以不传值,因为有缺省值(默认配置)
Param.print("Spark")("Scala") //Scala:Spark
import Context_Implicits._
//隐式参数没有传值,编译器会在全局范围内搜索 有没有implicit String类型的隐式值 并传入
Param.print("Hadoop") //Java:Hadoop
}
}
说明:在伴生对象中,定义隐式参数
implicit val default: String = "Java"
在Param对象中定义了一个方法,需要传递两个参数,第一个正常参数,第二个隐式参数
object Param {
//函数中用implicit关键字 定义隐式参数
def print(context: String)(implicit language: String){
println(language+":"+context)
}
}
在main方法中调用Param中的print方法,可以正常的传递两个参数进去,也可以只传一个参数context
只传一个参数hadoop,scala语言会隐式的把第二个参数传递进来,就是把Java传递进来。