二维码
微世推网

扫一扫关注

当前位置: 首页 » 快报资讯 » 今日快报 » 正文

好程序员大数据学习路线分享Scala系列之泛型

放大字体  缩小字体 发布日期:2022-12-11 15:59:21    作者:何海    浏览次数:314
导读

好程序员大数据学习路线分享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 element

好程序员大数据学习路线分享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

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

}

2.逆变

定义一个类型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)

}

3.上界

上界定义: 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)

4.下界

语法 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)

5 视界(view bounds)

注意:已过时,了解即可

视界定义: A <% B ,表示类型变量A 必须是 类型B`得子类,或者A能够隐式转换到B

class Pair_Int[T <% Comparable[T]] (val first: T, val second: T){

def bigger = if(firstpareTo(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)

val pair_int = new Pair_Int(3 ,45)

println(pair_int.bigger)

val pair_better = new Pair_Better(39 ,5)

println(pair_better.smaller)

}

}

6 上下文界定(context bounds)

上下文界定得形式为 T : M, 其中M 必须为泛型类, 必须存在一个M[T]得隐式值.

class Pair_Context[T : Ordering](val first: T, val second: T){

def smaller(implicit ord: Ordering[T]) =

if(ordpare(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)

}

}

 
(文/何海)
免责声明
• 
本文仅代表发布者:何海个人观点,本站未对其内容进行核实,请读者仅做参考,如若文中涉及有违公德、触犯法律的内容,一经发现,立即删除,需自行承担相应责任。涉及到版权或其他问题,请及时联系我们删除处理邮件:weilaitui@qq.com。
 

Copyright©2015-2025 粤公网安备 44030702000869号

粤ICP备16078936号

微信

关注
微信

微信二维码

WAP二维码

客服

联系
客服

联系客服:

24在线QQ: 770665880

客服电话: 020-82301567

E_mail邮箱: weilaitui@qq.com

微信公众号: weishitui

韩瑞 小英 张泽

工作时间:

周一至周五: 08:00 - 24:00

反馈

用户
反馈