Scala之泛型类

news/2024/7/5 7:29:16

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1. 泛型类

带有一个或多个类型参数的类是泛型的。
泛型类的定义:

//带有类型参数A的类定义class Stack[A] {private var elements: List[A] = Nil//泛型方法def push(x: A) { elements = x :: elements }def peek: A = elements.headdef pop(): A = {val currentTop = peekelements = elements.tailcurrentTop}
}

使用上述的泛型类,使用具体的类型代替类型参数 A 。

val stack = new Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop)  // prints 2
println(stack.pop)  // prints 1

2. 协变

定义一个类型 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 CatPrinterval animalPrinter: Printer[Animal] = new AnimalPrinterprintMyCat(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 = hdef 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 Birdval africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil())
val birdList: Node[Bird] = africanSwallowList
birdList.prepend(new EuropeanSwallow)

 

本文为原创文章,如果对你有一点点的帮助,别忘了点赞哦!比心!如需转载,请注明出处,谢谢!

 

转载于:https://my.oschina.net/aibinxiao/blog/2995173


http://lihuaxi.xjx100.cn/news/269272.html

相关文章

看论文不用来回翻了,这款PDF阅读神器能自动提取前文信息,科研效率max!

点击上方“视学算法”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达丰色 发自 凹非寺量子位 报道 | 公众号 QbitAI在阅读学术论文PDF时&#xff0c;各位是不是经常需要来回翻页查找某个专业术语或数学公式&#xff1f;满篇密密麻麻的数字与大…

数据库的介绍、分类、作用和特点

1. 数据库的介绍 数据库就是存储和管理数据的仓库&#xff0c;数据按照一定的格式进行存储&#xff0c;用户可以对数据库中的数据进行增加、修改、删除、查询等操作。 【在数据库中输错&#xff0c;按住“ctrlc”重新输入】 【之前基础用文件来存储的&#xff0c;数据库比文…

450g吐司烘烤温度_美晨烘焙丨会吐蛋黄的黄金吐司

咸蛋黄又来袭啦&#xff01;&#xff01;&#xff01;在烘焙界拥有崇高地位的咸蛋黄&#xff0c;在吃货中特别受爱戴的咸蛋黄&#xff0c;又来跟别人组队了&#xff0c;这次又跟哪位一起闪亮登场呢&#xff1f;登登登登&#xff0c;就是我们经常吃的吐司&#xff01;软绵外皮下…

详解 | SLAM回环检测问题

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达本文经知乎作者fishmarch授权转载&#xff0c;二次转载请联系作者原文&#xff1a;https://zhuanlan.zhihu.com/p/45573552在视觉SLAM问题中&#xff0c;位姿的估计往往是…

CSS a控制超链接文字样式

超链接的代码<a href"http://www.divcss5.com/" target"_blank" title"关于div css的网站">DIVCSS</a>解析如下&#xff1a;href 后跟被链接地址目标网站地址这里是http://www.divcss5.com/target _blank -- 在新窗口中打开链接 _pa…

TensorFlow、PyTorch之后,“国产”AI框架还有没有机会?

出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;众所周知&#xff0c;在机器学习框架领域&#xff0c;PyTorch、TensorFlow已分别成为目前学界和业界使用最广泛的两大实力玩家&#xff0c;而紧随其后的Keras、MXNet等框架也由于其自身的独特性受到开发者的喜爱。 202…

JavaScript获取当前日期,昨天,今天日期以及任意天数间隔日期

<script language"JavaScript" type"text/javascript"> function GetDateStr(AddDayCount) { var dd new Date(); dd.setDate(dd.getDate()AddDayCount);//获取AddDayCount天后的日期 var y dd.getYear(); var m dd.getMonth()1;//获取当前月份…

论文阅读笔记四十:Deformable ConvNets v2: More Deformable, Better Results(CVPR2018)

论文源址&#xff1a;https://arxiv.org/abs/1811.11168 摘要 可变形卷积的一个亮点是对于不同几何变化的物体具有适应性。但也存在一些问题&#xff0c;虽然相比传统的卷积网络&#xff0c;其神经网络的空间形状更接近于目标物体的形状&#xff0c;但有时会超出ROI区域&#x…