上界类型和正常类行为的差异

小菜蛾

我正在Scala中学习泛型,但我无法理解“正常”类层次结构和上界类型之间的区别。

看下面的示例:笼子可以收到Animal类,这意味着我可以通过Animal类或Dog类。上限参数同样有效。它们之间的实际区别是什么?什么时候应该使用其中一个?

class Animal
class Dog extends Animal

class Cage(animal: Animal)
val cage = new Cage(new Dog)

class AnotherCage[A <: Animal](animal: A)
val anotherCage = new AnotherCage(new Dog)
马里奥·加里奇(Mario Galic)

一个区别是参数静态类型,animal在前一种情况下,其类型为,Animal而在后一种情况下,其类型为,Dog因为类型参数A被具体类型替代Dog要了解差异,请尝试添加一个这样sound方法Dog

class Animal
class Dog extends Animal {
  def sound = "woof"
}

class Cage(val animal: Animal)
val cage = new Cage(new Dog)

class AnotherCage[A <: Animal](val animal: A)
val anotherCage = new AnotherCage(new Dog)

cage.animal.sound         // error
anotherCage.animal.sound  // ok

注意编译器怎么不知道sound在第一种情况的方法尽管被引用的运行时类animal的说法是Dog

参数化类型可以提供更强的类型安全性,并有助于避免使用进行类型转换asInstanceOf例如,假设我们有一个Dog和一个Cat

class Animal
class Dog extends Animal
class Cat extends Animal

并且我们定义了一种仅打开包含Dogs的笼子的方法

def openDogCage(cage: Cage): Dog =
  if (cage.animal.isInstanceOf[Dog]) cage.animal.asInstanceOf[Dog]
  else throw new IllegalArgumentException

def openAnotherDogCage(cage: AnotherCage[Dog]): Dog = cage.animal

但错误地为笼子提供了 Cat

val dog: Dog = openDogCage(new Cage(new Cat))               // runtime error
val dog: Dog = openAnotherDogCage(new AnotherCage(new Cat)) // compile-time error

然后注意在程序运行之前,参数化类型是如何在编译时捕获错误的。还要注意,在定义openDogCage仅使用子类型时,我们必须手动执行类型转换,asInstanceOf以使编译器确信该方法返回a Dog

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

有界类型参数(T扩展)和上界通配符(?扩展)之间的差异

来自分类Dev

Clojure中类型和类之间的差异

来自分类Dev

Haskell类型类和重复行为

来自分类Dev

xvalues:非类类型和类类型之间的差异

来自分类Dev

基本类型(int)和复杂类型(np.ndarray)在行为上的差异

来自分类Dev

类型类和包对象的奇怪的隐式解析行为

来自分类Dev

Clang和GCC中模棱两可的基类转换之间的行为差异

来自分类Dev

Python中super().__ init __()和显式超类__init __()之间的行为差异

来自分类Dev

上界Java通配符的有趣行为

来自分类Dev

for循环中if else和ifelse的行为差异

来自分类Dev

:=和[[之间有行为差异吗?

来自分类Dev

onkeydown 和 onkeyup 之间的行为差异

来自分类Dev

Solr - 'q' 和 'df' 查询的行为差异

来自分类Dev

Ubuntu 和 CentOS 之间链接行为的差异

来自分类Dev

“正常”构建和 ExternalProject_Add 之间的行为差异

来自分类Dev

基于类型声明的协议实现行为的差异

来自分类Dev

了解Scala中的上界和下界

来自分类Dev

类型类和从属类型

来自分类Dev

SQL DateTime> =和<=行为不正常

来自分类Dev

PureScript和类型类

来自分类Dev

Haskell和ML之间的类型系统差异

来自分类Dev

os.fork和multiprocessing.Process之间的行为差异

来自分类Dev

os.fork和multiprocessing.Process之间的行为差异

来自分类Dev

Windows 8.1和Windows 10之间的UAC高程行为差异

来自分类Dev

Java 11和Java 8 DecimalFormat行为之间的差异

来自分类Dev

python模块的终端和bash脚本之间的奇怪行为差异

来自分类Dev

Java 11和Java 8 DecimalFormat行为之间的差异

来自分类Dev

脚本和命令行之间的glob行为差异

来自分类Dev

Windows 8.1和Windows 10之间的UAC高程行为差异

Related 相关文章

  1. 1

    有界类型参数(T扩展)和上界通配符(?扩展)之间的差异

  2. 2

    Clojure中类型和类之间的差异

  3. 3

    Haskell类型类和重复行为

  4. 4

    xvalues:非类类型和类类型之间的差异

  5. 5

    基本类型(int)和复杂类型(np.ndarray)在行为上的差异

  6. 6

    类型类和包对象的奇怪的隐式解析行为

  7. 7

    Clang和GCC中模棱两可的基类转换之间的行为差异

  8. 8

    Python中super().__ init __()和显式超类__init __()之间的行为差异

  9. 9

    上界Java通配符的有趣行为

  10. 10

    for循环中if else和ifelse的行为差异

  11. 11

    :=和[[之间有行为差异吗?

  12. 12

    onkeydown 和 onkeyup 之间的行为差异

  13. 13

    Solr - 'q' 和 'df' 查询的行为差异

  14. 14

    Ubuntu 和 CentOS 之间链接行为的差异

  15. 15

    “正常”构建和 ExternalProject_Add 之间的行为差异

  16. 16

    基于类型声明的协议实现行为的差异

  17. 17

    了解Scala中的上界和下界

  18. 18

    类型类和从属类型

  19. 19

    SQL DateTime> =和<=行为不正常

  20. 20

    PureScript和类型类

  21. 21

    Haskell和ML之间的类型系统差异

  22. 22

    os.fork和multiprocessing.Process之间的行为差异

  23. 23

    os.fork和multiprocessing.Process之间的行为差异

  24. 24

    Windows 8.1和Windows 10之间的UAC高程行为差异

  25. 25

    Java 11和Java 8 DecimalFormat行为之间的差异

  26. 26

    python模块的终端和bash脚本之间的奇怪行为差异

  27. 27

    Java 11和Java 8 DecimalFormat行为之间的差异

  28. 28

    脚本和命令行之间的glob行为差异

  29. 29

    Windows 8.1和Windows 10之间的UAC高程行为差异

热门标签

归档