2017-07-23 66 views
3

我想設置一個變量的上限。斯卡拉的上限

trait Container { 
type A <: Number 
def value: A 
} 

然後,當我試圖得到一個值,我

object AnyNumber extends Container { 
def value = 2 
} 

我得到這個錯誤

<console>:25: error: overriding type A in trait Container with bounds <: Number; 
type A has incompatible type 
    type A = Int 
     ^

回答

1

你得到這個錯誤,因爲Int不是Number一個亞型,這是你放置的約束。

如果你想使用類型成員這些都是隱式轉換爲數字類型,我會在value使用Numeric[A]有一個隱含的證據:

trait Container { 
    type A 
    def value(implicit ev: Numeric[A]): A 
} 

object AnyNumber extends Container { 
    type A = Int 
    override def value(implicit ev: Numeric[Int]): Int = 2 
} 

注意我用Numeric[A]代替Number,這是斯卡拉等值。現在,這將工作:

def main(args: Array[String]): Unit = { 
    val intRes = AnyNumber.value 
} 

但試圖用這種具有String不會編譯:

def main(args: Array[String]): Unit = { 
    val strRes = StringNumber.value 
} 

結果:

Error:(24, 31) could not find implicit value for parameter ev: Numeric[String] 
    val strRes = StringNumber.value 
0

scala.Int只延伸scala.AnyVal,而你的上綁定是java.lang.Number

一種方式解決是使用java.lang.Integer而不是scala.Int,因爲它滿足您的邊界(java.lang.Number

如。

trait Container { 
    type A <: Number 
    def value: A 
} 

object AnyNumber extends Container { 
    type A = Integer 
    def value = 2 
} 

AnyNumber.value shouldBe 2 
0

如果它是可以接受的Container是一個類,而不是特質,下面是接近尤瓦的答案,但更符合人體工程學:

abstract class Container[A: Numeric] { 
    // optional, if you need a type member specifically 
    type _A = A 
    def value: A 
} 

object AnyNumber extends Container[Int] { 
    def value = 2 
} 

如果你想從API隱藏泛型參數,你可以這樣做:

sealed trait Container { 
    type A 
    val ev: Numeric[A] 
    def value: A 
} 

abstract class ContainerImpl[B](implicit val ev: Numeric[B]) extends Container { 
    type A = B 
}