给出方法下面的代码 foo
应该按运算符比较给定参数 bar
与 lowerBound
和 upperBound
所有都是相同的抽象类型 Bar
.
trait Foo {
type Bar <: Ordered[Bar]
val lowerBound: Bar
val upperBound: Bar
def foo(bar: Bar) = bar >= lowerBound && bar <= upperBound
}
这样的特质
Foo
可以定义。问题始于下面的具体类 FooImpl
.class FooImpl extends Foo {
type Bar = Int
val lowerBound = 0
val upperBound = 5
}
我明白
scala.Int
没有实现什么 scala.runtime.RichInt
确实有效 scala.math.Ordered[Int]
.定义类型 Bar
如 RichInt
相反,两者都不起作用,因为它不符合 scala.math.Ordered[RichInt]
.我第三次尝试定义类型 Bar
如 Ordered[Ord]
哪里Ord
声明为 type Ord
并在 FooImpl
中定义它如 Int
也没有用。一个可能接近的解决方案会是什么样子?
最佳答案
可能有更优雅的解决方案,但您可以通过将类型限制移动到方法而不是类型声明来实现这一点:
trait Foo {
type Bar
val lowerBound: Bar
val upperBound: Bar
def foo(bar: Bar)(implicit ev: Bar => Ordered[Bar]) = {
bar >= lowerBound && bar <= upperBound
}
}
那么你的
FooImpl
像你一样工作:class FooImpl extends Foo {
type Bar = Int
val lowerBound = 0
val upperBound = 5
}
来自 REPL:
scala> new FooImpl()
res0: FooImpl = FooImpl@2dbbec72
scala> res0.foo(3)
res1: Boolean = true
scala> res0.foo(7)
res2: Boolean = false
这里的缺点是可以使用无序类型扩展特征(尽管在这种情况下不能调用
foo
):class A // not Ordered
class BrokenFoo extends Foo {
type Bar = A
val lowerBound = new A
val upperBound = new A
} // compiles
new BrokenFoo().foo(new A) // doesn't compile
或者,您可以将需求保留在类级别(因此阻止任何人创建
BrokenFoo
),如下所示,但 FooImpl
必须稍微改变:trait Foo {
type Bar
implicit val baz: Bar => Ordered[Bar]
val lowerBound: Bar
val upperBound: Bar
def foo(bar: Bar) = { bar >= lowerBound && bar <= upperBound }
}
class FooImpl extends Foo {
type Bar = Int
val baz = implicitly[Bar => Ordered[Bar]]
val lowerBound = 0
val upperBound = 5
}
这个问题感觉就像view or context bounds应该适用,但不幸的是,您似乎无法在
type
中使用它们。声明或在特征的泛型类型参数中。
关于scala - 如何比较 Scala 特征中的有序抽象类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9254027/