==> 泛型类
---> T 可以代表任意类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class
Person[T]{
private
var
name
:
T
=
_
def
setName(name
:
T)
=
{
this
.name
=
name}
def
getName()
:
T
=
{
this
.name}
}
// ***********测试*****************
object
Person{
def
main(args
:
Array[String])
:
Unit
=
{
var
p
=
new
Person[String]()
p.setName(
"hello"
)
println(p.getName())
}
}
|
==> 泛型函数
---> 类型参数放在方法名之后
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//* 泛型函数
// 创建一个固定类型的数组
// 普通函数
def
mkInt(elems
:
Int*)
=
Array[Int](elems
:_
*)
def
mkString(str
:
String*)
=
"mkString"
// 使用泛型函数,可以接收任意类型
def
mkArray[T
:
ClassTag](elems
:
T*)
=
Array[T](elems
:_
*)
// ***********测试*****************
// 普通函数只能传入相对应类型的参数
mkInt(
1
,
2
,
3
)
mkString(
"hello"
,
"world"
)
// 泛型函数可以传入任意类型的参数
mkArray(
11.26
,
665
,
84
,
"hello"
)
|
==> 类型的上界和下界(Upper Bounds 和 Lower Bounds)
---> 用来定义泛型变量的范围 :
---> S <: T (上界) S 必须是 T 类型的子类或类本身
1
2
3
4
5
6
7
8
9
10
|
class
Person
1
{
def
gender()
=
{println(
"gender"
)}
}
class
Man
extends
Person
1
{
override
def
gender()
=
{println(
"man"
)}
}
class
Women
extends
Person
1
{
override
def
gender()
=
{println(
"women"
)}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
object
UpperBoundsAndLowerBounds {
// 定义一个泛型函数,通过上界的方式指定泛型的范围必须是 Person1 的子类或者Person1 类,并调用类中的 gender 方法
def
getGender[T <
:
Person
1
](g
:
T)
=
{g.gender()}
def
main(args
:
Array[String])
:
Unit
=
{
// 创建一个Person1 对象 ,调用getGender 方法调用 Personal 中的 gender 方法
var
p
:
Person
1
=
new
Person
1
getGender(p)
// 创建一个 Man 对象 ,通过 getGender 方法调用Man 类中的 gender 方法
var
m
=
new
Man
getGender(m)
}
}
|
---> U >: T(下界) U 必须是 T 类型的父类或类本身,此处不作示例,与上面例子类似,只是传入 getGender 方法中的参数必须是 Person1 类或其父类的对象
==> 视图界定 <%
---> 与类型的上界相似,但是比类型的上界适用范围更广,除了所有的子类与类本身,它还允许通过隐式转换得到的类型
1
2
3
4
5
6
7
8
|
def
int
2
String[T <
%
String](x
:
T, y
:
T)
=
{
println(x +
"*****"
+ y)
}
// ***********测试*****************
int
2
String(
"hello"
,
"world"
)
implicit
def
int
2
String
1
(n
:
Int)
:
String
=
{n.toString}
int
2
String(
100
,
120
)
|
==> 协变和逆变
---> 协变: 泛型变量的值可以是子类或类本身 在类型参数前加一个 “+” 符号 子类转换为父类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//* 协变和逆变 在类型的前面加入 +号,就可以使类的特征变为协变了
// 将子类对象转换为父类对象称为协变 +
// 将父类对象转换为子类对象称为逆变 -
package
demo
1
{
// 父类
class
Animal{}
// 子类
class
Bird
extends
Animal
class
Sparrow
extends
Bird
// 吃东西的类 协变
class
EatSomethings[+T](t
:
T){}
// ***********测试*****************
object
Demo
1
{
def
main(args
:
Array[String])
:
Unit
=
{
// 创建一个吃东西的对象
var
c
1
:
EatSomethings[Sparrow]
=
new
EatSomethings[Sparrow](
new
Sparrow)
var
c
2
:
EatSomethings[Animal]
=
c
1
}
}
}
|
---> 逆变: 泛型变量的值可以是父类或类本身 在类型参数前加一个 “ - ” 符号 父类转换为子类 例:省略
==> 隐式转换函数
---> 以关键字 implicit 申明
---> 单个参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class
Fruit(name
:
String){
def
getFruitName()
:
String
=
{name}
}
class
Monkey(f
:
Fruit){
def
say()
=
{println(
"Monkey like "
+ f.getFruitName()) }
}
// ***********测试*****************
object
ImplicitDemo {
def
main(args
:
Array[String])
:
Unit
=
{
var
f
:
Fruit
=
new
Fruit(
"bnanan"
)
// 调用 fruit 的方法,希望 Monkey这个say 方法来实现
// 需要将 fruit 的对象转换为 monkey 对象, 即定义一个隐匿转换函数
implicit
def
fruit
2
Monkey(f
:
Fruit)
:
Monkey
=
{
new
Monkey(f)}
// 将 fruit 对象转换为 Monkey 对象
// 调用Monkey中的 say 方法
f.say()
}
}
|
==> 隐式参数 使用 implicit 关键字申明的函数参数
---> 可以使用隐式参数进行类型转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 隐式参数
def
testParam(
implicit
name
:
String)
=
{println(
"The value is "
+ name)}
implicit
val
name
:
String
=
"这是一个隐式值"
// ***********测试*****************
testParam
//---------------------------------------------------------------
// 带隐式参数的泛型函数
// Ordered[T] 使类型可排序,
// 原型:def smaller
// (implicit order:T => Ordered[T])
def
smaller[T](a
:
T, b
:
T)(
implicit
order
:
T
=
> Ordered[T])
=
if
(order(a) < b) a
else
b
// ***********测试*****************
smaller(
100
,
56
)
smaller(
"hello"
,
"hi"
)
|
==> 隐式类 对类 增加 implicit 限定 的类,其主要作用就是对类的功能增强
---> 编写一个隐式类,使类实现更多的功能
1
2
3
4
5
6
7
8
9
10
11
12
|
object
testImplicit {
// 定义一个隐式类
implicit
class
Calc(x
:
Int){
def
add(a
:
Int)
:
Int
=
a + x
}
// ***********测试*****************
def
main(args
:
Array[String])
:
Unit
=
{
println(
"两个数字的和:"
+
1
.add(
2
))
}
}
|
---> 程序过程分析:
--- 当 1.add(2)时,scala 的编译器不会报错,在当前域中查找,有没有 implicit 修饰的,同时可以将 Int 作为参数的构造器,并且具有 add 方法的类,通过查找,找到 Calc
--- 利用隐式类 Calc 来执行 add 方法
==> 个人总结:
---> 通过泛型,可以使我们定义一个模具,就像蛋糕的模具,我们可以分别放入草莓,蓝莓等不同的原料加工出不同口味的蛋糕来
---> 通过使用 上界,下界,视图界定,协变,逆变,对泛型的范围制定规则,使我们可以传入的符合规则的参数
---> 隐式函数,隐式参数,隐式类,会在程序运行时首先被查找,若有符合 以 implicit 修饰的参数,函数以及类,先执行,然后才运行程序
若总结有误,还请多多指教,谢谢!!!