【问题标题】:scala type bounds and variancescala类型边界和方差
【发布时间】:2021-01-24 08:45:19
【问题描述】:

请解释一下什么是 scala 类型的规则以及为什么应该在这里使用

我有类型层次结构

class A
class B extends A
class C extends A
cladd D extends C

其他类型类

class Hub(init) {
 def add(elem): Hub = new Hub(elem)
}

我需要编辑 HubHub.add 的输入,它应该像这样工作

val a : Hub[D] = Hub(new D)
val b : Hub[A] = a.add(new B)
val c : Hub[A] = b.add(new C)
val d : Hub[A] = c.add(new D)

这应该是编译错误

val e : Hub[C] = b.add(new C)

我应该如何编辑它以及为什么?

附:这不是有效的 scala 代码,这是为了类型示例

【问题讨论】:

    标签: scala generics types typeclass


    【解决方案1】:

    使add 具有适当的类型界限[B >: A] 的参数(有关典型示例,请参阅标准库集合的方法的一半)。

    class Hub[A](a: A) {
     def add[B >: A](b: B): Hub[B] = new Hub[B](b)
    }
    object Hub {
      def apply[A](a: A): Hub[A] = new Hub[A](a)
    }
    
    val a : Hub[D] = Hub(new D)
    val b : Hub[A] = a.add(new B)
    val c : Hub[A] = b.add(new C)
    val d : Hub[A] = c.add(new D)
    // val e : Hub[C] = b.add(new C) type mismatch
    

    [B >: A](b: B) 编译器试图推断B s 两者都会:

    • A的超类型
    • 成为传递值的超类型,以便可以向上转换为它

    【讨论】:

    • 谢谢,我想我明白我的错误了。我认为如果我们得到add[P >: Q](elem: P) 并且我们有a = Hub[A],我们就不能传递a.add(new D),因为D 是A 的子类型并且我们得到[P >: Q],这意味着我们可以传递子类型,但是这将是对超类型的推断。我说的对吗?
    • 好吧,基本上编译器会发现 B 的值可以向上转换为 elem 并且 A 值可以向上转换为它。并且编译器将尝试找到符合这些要求的最具体的类型(最小上限 - LUB),因为 Any 将始终有效,并且几乎永远不会是我们需要的。
    猜你喜欢
    • 2013-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 2022-12-09
    • 1970-01-01
    • 2018-02-02
    相关资源
    最近更新 更多