上界类型和正常类行为的差异 [英] Difference of Upper Bounded Type and normal class behavior

查看:67
本文介绍了上界类型和正常类行为的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am studying Generics in Scala and I can't understand the difference between a "normal" class hierarchy and the Upper Bound type.

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

Looking at the example below: Cage can receive the class Animal, which means that I can pass either the class Animal or the class Dog. The same is valid for the upper bound parameter. What is the practical difference between them? When should I use one or the other?

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)

推荐答案

animal参数的 static 类型是一个区别,在前一种情况下,它在Animal中键入为Animal.在后一种情况下,将其键入为Dog,因为类型参数A被具体类型Dog代替.要了解差异,请尝试向Dog添加sound方法,如下所示

One difference is in the static type of animal parameter where in the former case it is typed as Animal whilst in latter case it is typed as Dog because the type parameter A is substituted with concrete type Dog . To see the difference try adding a sound method to Dog like so

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

请注意,尽管animal参数引用的运行时类是Dog,但在第一种情况下编译器如何不了解sound方法.

Note how compiler is not aware of sound method in the first case despite the fact that the runtime class referenced by animal argument is Dog.

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

Parameterized types can provide stronger type-safety and help avoid the need for type casting with asInstanceOf. For example, let's say we have a Dog and a Cat

class Animal
class Dog extends Animal
class Cat extends Animal

,我们定义了一种仅打开包含Dog s

and we define a method that opens only cages containing 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

but erroneously provide a cage with a Cat

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

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

then notice how parameterzied types caught the error at compile-time before the program even ran. Also notice how in definition of openDogCage when using just subtyping we had to manually perform a type cast with asInstanceOf to convince the compiler that method returns a Dog.

这篇关于上界类型和正常类行为的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆