首页 > 大数据 > 数据挖掘 > 深圳大数据学习:泛型--【千锋】
带有一个或多个类型参数的类是泛型的。
泛型类的定义:
//
带有类型参数
A
的类定义
class
Stack[A] {
private
var
elements: List[A] = Nil
//
泛型方法
def
push
(x: A) { elements = x :: elements }
def
peek: A = elements.
head
def
pop
(): A = {
val
currentTop = peek
elements = elements.
tail
currentTop
}
}
泛型类的使用,用具体的类型代替类型参数A。
val
stack =
new
Stack[Int]
stack.
push
(
1
)
stack.
push
(
2
)
println
(stack.
pop
)
// prints 2
println
(stack.
pop
)
// prints 1
定义一个类型List[+A],如果A是协变的,意思是:对类型A和B,A是B的子类型,那么List[A]是List[B]的子类型。
abstract
class
Animal {
def
name: String
}
case
class
Cat
(name: String)
extends
Animal
case
class
Dog
(name: String)
extends
Animal
Scala标准库有一个泛型类sealed abstract class List[+A],因为其中的类型参数是协变的,那么下面的程序调用时成功的。
object
CovarianceTest
extends
App {
//
定义参数类型
List[Animal]
def
printAnimalNames
(animals: List[Animal]): Unit = {
animals.
foreach
{ animal =>
println
(animal.
name
)
}
}
val
cats: List[Cat] = List(
Cat
(
"Whiskers"
),
Cat
(
"Tom"
))
val
dogs: List[Dog] = List(
Dog
(
"Fido"
),
Dog
(
"Rex"
))
//
传入参数类型为
List[Cat]
printAnimalNames
(cats)
// Whiskers
// Tom
//
传入参数类型为
List[Dog]
printAnimalNames
(dogs)
// Fido
// Rex
}
定义一个类型Writer[-A],如果A是逆变的,意思是:对类型A和B,A是B的子类型,那么Writer[B]是Writer[A]的子类型。
abstract
class
Animal {
def
name: String
}
case
class
Cat
(name: String)
extends
Animal
case
class
Dog
(name: String)
extends
Animal
定义对应上述类进行操作的打印信息类
abstract
class
Printer[-A] {
def
print
(value: A): Unit
}
class
AnimalPrinter
extends
Printer[Animal] {
def
print
(animal: Animal): Unit =
println
(
"The animal's name is: "
+ animal.
name
)
}
class
CatPrinter
extends
Printer[Cat] {
def
print
(cat: Cat): Unit =
println
(
"The cat's name is: "
+ cat.
name
)
}
逆变的测试
object
ContravarianceTest
extends
App {
val
myCat: Cat =
Cat
(
"Boots"
)
//
定义参数类型为
Printer[Cat]
def
printMyCat
(printer: Printer[Cat]): Unit = {
printer.
print
(myCat)
}
val
catPrinter: Printer[Cat] =
new
CatPrinter
val
animalPrinter: Printer[Animal] =
new
AnimalPrinter
printMyCat
(catPrinter)
//
可以传入参数类型为
Printer[Animal]
printMyCat
(animalPrinter)
}
上界定义: T <: A ,表示类型变量 T 必须是 类型 A 子类
abstract
class
Animal {
def
name: String
}
abstract
class
Pet
extends
Animal {}
class
Cat
extends
Pet {
override
def
name: String =
"Cat"
}
class
Dog
extends
Pet {
override
def
name: String =
"Dog"
}
class
Lion
extends
Animal {
override
def
name: String =
"Lion"
}
//
参数类型须是
Pet
类型的子类
class
PetContainer[P <: Pet](p: P) {
def
pet: P = p
}
//Dog
是
Pet
类型的子类
val
dogContainer =
new
PetContainer[Dog](
new
Dog)
//Cat
是
Pet
类型的子类
val
catContainer =
new
PetContainer[Cat](
new
Cat)
//Lion
不是
Pet
类型的子类,编译通不过
// val lionContainer = new PetContainer[Lion](new Lion)
语法 B >: A 表示参数类型或抽象类型 B 须是类型A的父类。通常,A是类的类型参数,B是方法的类型参数。

上面这段代码,因为作为协变类型的B,出现在需要逆变类型的函数参数中,导致编译不通过。解决这个问题,就需要用到下界的概念。
trait Node[+B] {
def prepend[U >: B](elem: U): Node[U]
}
case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
def head: B = h
def tail: Node[B] = t
}
case class Nil[+B]() extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
}
测试
trait Bird
case class AfricanSwallow() extends Bird
case class EuropeanSwallow() extends Bird
val africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil())
val birdList: Node[Bird] = africanSwallowList
birdList.prepend(new EuropeanSwallow)
注意 :已过时,了解即可
视界定义: A <% B ,表示类型变量 A 必须是 类型 B`的子类,或者A能够隐式转换到B
class
Pair_Int[T <% Comparable[T]] (
val
first: T,
val
second: T){
def
bigger =
if
(first.
compareTo
(second) >
0
) first
else
second
}
class
Pair_Better[T <% Ordered[T]](
val
first: T,
val
second: T){
def
smaller =
if
(first < second) first
else
second
}
object
View_Bound {
def
main
(args: Array[String]) {
//
因为
Pair[String]
是
Comparable[T]
的子类型
,
所以
String
有
compareTo
方法
val
pair =
new
Pair_Int
(
"Spark"
,
"Hadoop"
);
println
(pair.
bigger
)
/**
*
Scala
语言里
Int
类型没有实现
Comparable
;
*
那么该如何解决这个问题那
;
*
在scala
里
RichInt
实现了
Comparable
,
如果我们把int
转换为
RichInt
类型就可以这样实例化了
.
*
在scala
里
<
%
就起这个作用
,
需要修改Pair
里的
<:
为<%
把T
类型隐身转换为
Comparable[Int]
* String
可以被转换为RichString.
而RichString
是
Ordered[String]
的子类.
*
/
val pair_int
=
new
Pair_Int
(3
,45)
println
(pair_int.bigger)
val pair_better
=
new
Pair_Better
(39
,5)
println
(pair_better.smaller)
}
}
上下文界定的形式为 T : M, 其中M 必须为泛型类, 必须存在一个M[T]的隐式值.
class
Pair_Context[T : Ordering](
val
first: T,
val
second: T){
def
smaller
(
implicit
ord: Ordering[T]) =
if
(ord.
compare
(first, second) <
0
) first
else
second
}
object
Context_Bound {
def
main
(args: Array[String]) {
val
pair =
new
Pair_Context
(
"Spark"
,
"Hadoop"
)
println
(pair.
smaller
)
val
int
=
new
Pair_Context
(
3
,
5
)
println
(
int
.
smaller
)
}
}
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69947096/viewspace-2660984/ ,如需转载,请注明出处,否则将追究法律责任。