独立于外部类实例

时间:2015-09-03 17:08:04

标签: scala inner-classes traits

我试图指定所有AbstractTaskKey都是有序的,无论它们属于哪个AbstractTaskKeys容器。

如下面的代码所示,很容易为每个特定的外部类指定一个顺序,但这意味着在每个不同的地方我想要排序allKeys我需要使用sortBy(或定义一个隐含的ord这是专门针对范围内的任何外外类。

我希望能够为AbstractTaskKey定义一个Ordered实例,该实例适用于AbstractTaskKeys的所有子类。

我尝试在其他SO帖子建议的不同地方添加各种方差注释,子类和通配符,但无济于事。

如何使我的AbstractTaskKey的Ordered实例(或Ordering)变得通用?

object HelloWorld {
  def main(args: Array[String]) {
    val someTaskKeyConsumer = new SomeTaskKeyConsumer[FooTaskKeys](FooTaskKeys)
    println(someTaskKeyConsumer.sortedKeysLength)
  }
}

trait AbstractTaskKeys {
  // Tried: traitAbstractTaskKey extends Ordered[...] too
  trait AbstractTaskKey {val id: Int}

  // Really I want _#AbstractTaskKey or (_ <: AbstractTaskKeys)#AbstractTaskKey
  implicit val ord: Ordering[AbstractTaskKey] = Ordering.by(_.id)
  val allKeys: List[AbstractTaskKey]
}

class SomeTaskKeyConsumer[TaskKeys <: AbstractTaskKeys](taskKeys: TaskKeys) {
  def sortedKeysLength: Int
    // No implicit Ordering defined for SomeTaskKeyConsumer.this.taskKeys.AbstractTaskKey
    //= taskKeys.allKeys.sorted.length     
    = taskKeys.allKeys.sortBy(_.id).length // works fine
}

trait FooTaskKeys extends AbstractTaskKeys
object FooTaskKeys extends FooTaskKeys {
  case object FooTask0 extends AbstractTaskKey {val id = 0}
  val allKeys = List(FooTask0)

1 个答案:

答案 0 :(得分:0)

关键是将隐式Ordering放在AbstractTaskKey的伴随对象中,以便它在编译器在需要填充隐式时搜索的范围内。

trait AbstractTaskKeys {
  trait AbstractTaskKey {val id: Int}
  object AbstractTaskKey {
    implicit val ord: Ordering[AbstractTaskKey] = Ordering.by(_.id)
  }
  val allKeys: List[AbstractTaskKey]
}

class SomeTaskKeyConsumer[TaskKeys <: AbstractTaskKeys](taskKeys: TaskKeys) {
  def sortedKeysLength: Int = taskKeys.allKeys.sorted.length
}

这不允许您比较AbstractTaskKey的不同封闭实例中AbstractTaskKeys的实例,但这似乎并不是您正在寻找的内容。如果是,您可以使用路径相关类型Ordering定义AbstractTaskKeys#AbstractTaskKey

implicit val ord: Ordering[AbstractTaskKeys#AbstractTaskKey] = Ordering.by(_.id)