簡體   English   中英

如何比較Scala特征中的Ordered抽象類型?

[英]How to compare Ordered abstract type in Scala trait?

給定下面的代碼,方法foo應該比較操作符給定的參數barlowerBoundupperBound都是相同的抽象類型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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM