[英]How to compare Ordered abstract type in Scala trait?
Given the code below the method foo
should compare operator-wise a given parameter bar
with the lowerBound
and upperBound
all being of the same abstract type Bar
. 给定下面的代码,方法
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
}
This way the trait Foo
can be defined. 这样就可以定义特征
Foo
。 The problems start with the below concrete class FooImpl
. 问题从下面的具体类
FooImpl
。
class FooImpl extends Foo {
type Bar = Int
val lowerBound = 0
val upperBound = 5
}
I understand that scala.Int
isn't implementing what scala.runtime.RichInt
does, effectively scala.math.Ordered[Int]
. 我知道
scala.Int
没有实现scala.runtime.RichInt
功能,实际上是scala.math.Ordered[Int]
。 Defining type Bar
as RichInt
instead neither works as it does not conform to scala.math.Ordered[RichInt]
. 将类型
Bar
定义为RichInt
则不起作用,因为它不符合scala.math.Ordered[RichInt]
。 My third attempt to define type Bar
as Ordered[Ord]
where Ord
is declared as type Ord
and defining it in FooImpl
as Int
also did not work. 我第三次尝试将类型
Bar
定义为Ordered[Ord]
,其中Ord
被声明为type Ord
并在FooImpl
其定义为Int
也不起作用。
How would a possibly close solution look like? 一个可能接近的解决方案怎么样?
There may be a more elegant solution, but you can achieve this by moving the restriction on the type to the method, rather than the type declaration: 可能有一个更优雅的解决方案,但您可以通过将类型的限制移动到方法而不是类型声明来实现此目的:
trait Foo {
type Bar
val lowerBound: Bar
val upperBound: Bar
def foo(bar: Bar)(implicit ev: Bar => Ordered[Bar]) = {
bar >= lowerBound && bar <= upperBound
}
}
Then your FooImpl
works as you have it: 然后你的
FooImpl
就像你拥有它一样:
class FooImpl extends Foo {
type Bar = Int
val lowerBound = 0
val upperBound = 5
}
From the REPL: 来自REPL:
scala> new FooImpl()
res0: FooImpl = FooImpl@2dbbec72
scala> res0.foo(3)
res1: Boolean = true
scala> res0.foo(7)
res2: Boolean = false
The disadvantage here is that the trait can be extended with unordered types (although foo
can't be called in that case): 这里的缺点是特性可以用无序类型扩展(尽管在这种情况下不能调用
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
Alternatively, you can keep the requirement at the class level (and therefore stop anyone creating a BrokenFoo
) as follows, but FooImpl
has to change slightly: 或者,您可以将需求保持在类级别(因此阻止任何创建
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
}
This problem feels like view or context bounds should be applicable, but unfortunately it doesn't seem like you can use them either in type
declarations or in generic type parameters on traits. 这个问题感觉像视图或上下文边界应该适用,但不幸的是,你似乎不能在
type
声明或特征上的泛型类型参数中使用它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.