2017-07-23 36 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 
}