博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Scala 语言学习之泛型(7)
阅读量:6416 次
发布时间:2019-06-23

本文共 4473 字,大约阅读时间需要 14 分钟。

==> 泛型类

        ---> T 可以代表任意类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class 
Person[T]{
  
private 
var 
name
:
= 
_
 
  
def 
setName(name
:
T) 
= 
{
this
.name 
= 
name}
  
def 
getName()
:
= 
{
this
.name}
}
 
// ***********测试*****************
object 
Person{
  
def 
main(args
:
Array[String])
:
Unit 
= 
{
    
var 
= 
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 
= 
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
:
=
> 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 修饰的参数,函数以及类,先执行,然后才运行程序

若总结有误,还请多多指教,谢谢!!!

本文转自   tianshuai369   51CTO博客,原文链接:http://blog.51cto.com/songqinglong/2072568

转载地址:http://jpkra.baihongyu.com/

你可能感兴趣的文章
洛谷P4015 运输问题(费用流)
查看>>
对“TD信息树”的使用体验
查看>>
c++排序函数详解
查看>>
基于RabbitMQ rpc实现的主机管理
查看>>
进程划分
查看>>
js前台实现上传图片的预览
查看>>
系统架构师谈企业应用架构之系统建模(四)
查看>>
日三省
查看>>
ExtJS3 布局
查看>>
hdu6191(树上启发式合并)
查看>>
利用sqoop对mysql执行DML操作
查看>>
hibernate中视图的映射
查看>>
Ionic3 UI组件之 ImageViewer
查看>>
flask框架----flask基础
查看>>
flask框架----flask-script组件
查看>>
Oracle之RMAN备份及还原
查看>>
蓝桥杯-学校的第一次练习题
查看>>
spring中注解说明
查看>>
hdu 4135 -Co-prime
查看>>
二叉树的建立与先序、中序、后序遍历
查看>>