【scala系列】12、隐式转换、视图界定


1. 隐式转换

  • 隐式转换是scala中一种特殊的功能,能在不改动已有class设计的情况下为class添加新的方法
  • 隐式转换是把一种类型安全地转成另一种类型,原数据类型将拥有新的数据类型的所有方法,也可以看成是对类的一种增强
  • 定义隐式转换的关键字是 implicit
  • 隐式转换的常用命名方式是 one2one
  • 隐私转换分为两种:
    1. 隐式转换函数
    2. 隐式转换值

1.1 隐式转换函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

class ImplicitDemo1_1(var name: String)

class ImplicitDemo1_2(var name: String)

class ImplicitDemo1_3(var name: String)


/**
* 扩大隐式转换的作用域
* 我们可以将隐式转换函数或者值定义在object对象中,来扩大隐式转换的作用域
* 以后多个地方使用到的话,我们直接可以使用import 将对应的隐式转换函数或者值导入即可
* 注意:y隐式转换函数或者值只能定义在object对象中
*
*/
object ImplicitDemo1_4{
/**
* 隐式转换函数
* 将函数放在 object 总增大其作用域
* 隐式转换函数要在使用前定义或引用
*/

implicit def any2ImplicitDemo1_1(any: Any) = {
// 判断传过来的数据类型 如果是ImplicitDemo1_2
if (any.isInstanceOf[ImplicitDemo1_2]) {

// 自动转换为 ImplicitDemo1_1
val i2 = any.asInstanceOf[ImplicitDemo1_2]
new ImplicitDemo1_1(i2.name)

} else if (any.isInstanceOf[ImplicitDemo1_3]) {
val i3 = any.asInstanceOf[ImplicitDemo1_3]
new ImplicitDemo1_1(i3.name)
} else {
null
}
}
}

object ImplicitDemo1 {

def whichClass(p: ImplicitDemo1_1) = {
if (p != null) {
println("is ImplicitDemo1_1:" + p.name)
} else {
println("no ImplicitDemo1_1:")
}
}

def main(args: Array[String]): Unit = {
val i1 = new ImplicitDemo1_1("xiaom")
val i2 = new ImplicitDemo1_2("xioah")
val i3 = new ImplicitDemo1_3("xioag")
//编译器运行时会检测有没有隐式转换函数 去转换类型
whichClass(i1) //is ImplicitDemo1_1:xiaom

// 引入隐士转换
import ImplicitDemo1_4.any2ImplicitDemo1_1
// 未定义隐式转换时传送参数类型不匹配无法传送 i2, 定义后即可使用
whichClass(i2) //is ImplicitDemo1_1:xioah
whichClass(i3) //is ImplicitDemo1_1:xioag

}
}

1.2 隐式参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

class ImplicitDemo2_1(var name:String){
def write(content:String)= println(s"name=$name, content=$content")
}

object ImplicitDemo2 {
/**
* 在方法中被implicit修饰的参数被称为隐式参数
* @param name
* @param p
*/
def singForExam(content:String)(implicit i1:ImplicitDemo2_1)={
i1.write(content)
}

def main(args: Array[String]): Unit = {

// 隐式参数必须在上下文中有用隐式定义的对应类型
implicit val i1 = new ImplicitDemo2_1("你好")
//implicit val i2 = new ImplicitDemo2_1("hello")//一起多个会报错
singForExam("小明") //name=你好, content=小明

//i1.write("xiaom") //name=你好, content=xiaom

//implicit val i3 = new ImplicitDemo2_1("hello")//一起多个会报错
//singForExam("黑") //name=你好, content=小明
}
}

1.3 隐式类型转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

object ImplicitDemo3 {

// 需要时把String->Int
implicit def foo(s:String):Int = Integer.parseInt(s)

// 做求和计算
def add(a:Int, b:Int) = a+b

def main(args: Array[String]): Unit = {

// 计算时先把"100"隐式转换为100
println(add("100",8)) // 108
}
}

1.4 隐式为Int增加next 与求阶乘方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

object ImplicitDemo3_1 {

// 隐士转换函数 为 Int 类型增加next方法
implicit def next(n: Int) = new {
def next = n + 1
}


// 定义阶乘函数
def pow(n: Int, m: Int): Int = if (m == 0) 1 else n * pow(n, m - 1)

// 定义隐式转换函数 **
implicit def foo(n: Int) = new {
def **(m: Int) = pow(n, m)
}

def main(args: Array[String]): Unit = {

println(10.next) // 11

println(2**10) // 1024

}
}

1.5 隐式对类的增强

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
object ImplicitDemo4 {
implicit def file2RichFile(file:File):RichFile = new RichFile(file)
def main(args: Array[String]): Unit = {
val file = new File("/opt/apache-maven-3.6.2/conf/settings.xml")
file.read()
}
}

/**
* 在这里将file 转换为RichFIle 相当于对类的增强
* @param file
*/
class RichFile(var file:File){
def read()={
val content = Source.fromFile(file).mkString
println(content)
}
}

2. 视图界定

  • 视图界定用 <% 来表示 (T <% Class1),表示 T 只能是 Class1 的子类或者 T 能隐式转换成 Class1 类,
  • 视图界定是对泛型中类的上边界的一种增强
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

class Human(var name:String){
def sayHello(): Unit ={
println(s"hello, I'm $name")
}
def makeFriends(p:Human)={
sayHello()
p.sayHello()
}
}

class Student(name:String) extends Human(name)

class Cat(var name:String){
def sayHello(): Unit ={
println(s"I'm a cat name is $name")
}
}
//泛型T 只能是Human 及其子类,或者T类能够隐式的转换成Human的类型
class Party [ T<% Human](p1:T,p2:T){
p1.makeFriends(p2)
}

object ImplicitDemo05 {
def main(args: Array[String]): Unit = {
val human1 = new Human("小明")
val human2 = new Human("小红")
val party1 = new Party[Human](human1,human2)
/**
* hello, I'm 小明
* hello, I'm 小红
*/

val s1 = new Student("小学生")
val s2 = new Student("中学生")
val party2 = new Party[Student](s1,s2)
/**
* hello, I'm 小学生
* hello, I'm 中学生
*/



val c1 = new Cat("加菲猫")
val c2 = new Cat("小花猫")

// 对Cat 类进行隐式转换
implicit def cat2Human(cat:Cat):Human ={
new Human(cat.name)
}

//因为Cat 不是Human的子类 所以必须用隐式转换才能使用
val party3 = new Party[Cat](c1,c2)

/**
* hello, I'm 加菲猫
* hello, I'm 小花猫
*/
}
}


文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
  目录