鉴于下面的代码,方法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
也无法正常工作
可能接近的解决方案如何?
答案 0 :(得分:8)
可能有更优雅的解决方案,但您可以通过将类型限制移到方法而不是类型声明来实现此目的:
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
声明或特征上的泛型类型参数中使用它们。