4

我在 Scala 中正确输入时遇到了麻烦——我想做这样的事情,在类层次结构上强加 Ordered,但是子类允许 compare 方法只能使用它们自己类型的参数

abstract class Parent extends Ordered
class A extends Parent {
  override def compare(that : A) = 1
}
class B extends Parent {
  override def compare(that : B) = 1
}

以下工作,但我被迫永远将类型特异性强加给 Parent 及其子类。这只会成为正确推理的噩梦。

abstract class Parent[T <: Parent[_]] extends Ordered[T]
class A extends Parent[A] {
  override def compare(that : A) = 1
}
class B extends Parent[A] {
  override def compare(that : B) = 1
}

有没有更简单的方法来强制 Ordered[T] 的子类上的类型?

4

4 回答 4

2

为什么不只是

abstract class Parent
class A extends Parent with Ordered[A] {...}
class B extends Parent with Ordered[B] {...}

正如其他人指出的那样,根据您的比较标准,Parent不会对 s 序列进行排序,因为它的子类不可比较。只有它的子类是Ordered,所以在那里实现特征。

于 2012-06-02T21:57:55.110 回答
1

我同意这个问题有点烦人,但如果你正在寻找的行为是允许的,那就有点奇怪了。假设你做了

trait Parent {
    this: Ordered[ThisType]
}

// Does A need to be Ordered[A]?
trait A extends Parent

// Should B, C be comparable? If A is Ordered, then they
// have to be. But is this what you want?
class B extends A
class C extends A

// Now what?
class D extends B

基本上,使用继承来强制一些这样的属性会有点奇怪......它可能在理论上可以工作,但这将背离继承的含义。相反,您可以Ordered在需要时在方法中指定约束:

def foo[T <: Ordered[T]](x: T) = ...

或者,如果您想将Ordered约束和可能的其他约束分组在一个通用名称下,您可以创建一个类型类样式的特征:

trait Parent[A] {
    val order: Ordering[A]
}

def foo[T : Parent](x: T, y: T) {
    println(implicitly[Parent[T]].order.compare(x, y))
}

此解决方案的一个不幸方面是您无法指定sealed; 如果有人有办法解决这个问题,我会很感兴趣。否则,您可以使用依赖类型的编程语言,它们在这类事情上要好一些。

于 2012-06-02T16:26:04.357 回答
1

路易吉,我认为这是正确的答案。我想我是从 Java OO 范式来解决这个问题的,在这种范式中,通常需要在不了解其底层类型的情况下订购一组父母。至少在我的小环境中,我开始意识到,如果我正确设置了我的功能方法,我知道集合的类型。

于 2012-06-03T10:49:47.063 回答
0

谢谢,这是一个非常好的见解——以前从未想过。我只是把它作为一个解决方案,但坦率地说,它看起来有点臭,这让我有点紧张。注释?

abstract class Parent extends Ordered[Parent] {
  override def compare(that : Parent) : Int = {
    (this, that) match {
      case (x : A, y : A) =>  x.compare(y)
      case (x : B, y : B) =>  x.compare(y)
      case _ =>  throw new ClassCastException
    }
  }
}
class A extends Parent {
  def compare(that : A) = 1
}
class B extends Parent {
  def compare(that : B) = 1
}
于 2012-06-02T16:51:26.767 回答