Scala之旅(TOUR OF SCALA)——类型下限(LOWER TYPE BOUNDS)

当类型上限限制了一个类型是另一个类型的子类时,类型下限则声明了一个类型是另一个类型的父类。这个表达式 B >: A 表示类型参数 B 或抽象类型 B 是类型 A 的父类。在大部分例子中, A 将成为类的类型参数, B 将成为方法的类型参数。

下面是一个有用的例子:

trait Node[+B] {
    def prepend(elem: B): Node[B]
}

case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
    def prepend(elem: B): ListNode[B] = ListNode(elem, this)
    def head: B = h
    def tail: Node[B] = t
}

case class Nil[+B]() extends Node[B] {
    def prepend(elem: B): ListNode[B] = ListNode(elem, this)
}

这个程序实现了一个单链表。 Nil 代表一个空的元素(一个空表)。class ListNode 是一个拥有 B 类型元素(头)的结点,而且指向列表的剩下的部分(尾)。 class Node 和它的子类因为有 +B 注解所以是协变。

然而,这个程序并不能通过编译因为在 prepend 方法中的参数 elem 的类型是声明为协变的 B 类型,也不能工作因为函数的参数类型是逆变的且返回类型才是协变的。

为了修复这个BUG,我们需要翻转 prepend 方法中的 elem 参数的变性。通过一个新的类型参数 U 作为 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())

Node[bird]africanSwallow 赋值,但是可以接受 EuropeanSwallow 的实例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值