首页 > 大数据 > 数据挖掘 > 好程序员大数据学习路线分享Scala系列之泛型
好程序员大数据学习路线分享Scala系列之泛型,带有一个或多个类型参数的类是泛型的。
泛型类的定义:
//
带有类型参数
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/69913892/viewspace-2659377/ ,如需转载,请注明出处,否则将追究法律责任。