【问题标题】:Automatically inferred generic type in trait在 trait 中自动推断泛型类型
【发布时间】:2015-08-07 17:43:39
【问题描述】:

我想要一个通用的基类,它可以混合一些特性。

是否可以让 mixin 自动采用基类的泛型类型?

abstract class Base[T] {
  def foo: T = ???
  def bar(value: T): Boolean
}

trait MixinA {
  self: Base[U] => // U should be automatically bound to T of Base[T]
  def bar(value: U): Boolean = false
}

【问题讨论】:

    标签: scala generics inheritance


    【解决方案1】:

    您可以使用Base 中的抽象类型实现接近此目的:

    abstract class Base[T] {
      type U <: T
      def foo: U = ???
      def bar(value: U): Boolean
    }
    
    trait MixinA {
      self: Base[_] =>
      final def bar(value: U): Boolean = false
    }
    

    REPL 测试:

    scala> class Impl extends Base[Int] with MixinA
    defined class Impl
    
    scala> val i = new Impl
    i: Impl = Impl@7ca5cc9e
    
    scala> val x: Int = i.foo
    scala.NotImplementedError: an implementation is missing
      at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225)
      at Base.foo(<console>:9)
      ... 33 elided
    

    如您所见,编译器正确确定i.fooInt 的子类型(具体而言,它 Int),因此可以分配给x(这里的例外只是因为你没有实现它的主体)。

    【讨论】:

      【解决方案2】:

      在这种情况下,您需要将U 作为您的MixinA 的类型参数。

      trait MixinA[U] { self: Base[U] => ...
      

      类型参数在某种程度上类似于函数参数,如果声明了它们,则需要从某个地方传递它们(没有魔法)。

      【讨论】:

      • 我想避免再次为 mixin 显式指定泛型类型:new Base[Int] with MixinA 而不是 new Base[Int] with MixinA[Int]
      • MixinA 中具有类型参数U 是必需的,以便它可以使用适当参数化的基本特征。否则使用类型成员。
      猜你喜欢
      • 2020-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多