[英]How to compare Ordered abstract type in Scala trait?
給定下面的代碼,方法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
}
這個問題感覺像視圖或上下文邊界應該適用,但不幸的是,你似乎不能在type
聲明或特征上的泛型類型參數中使用它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.