通用数据类型的 Scala 方法
Scala Method on Generic Data Type
我正在尝试创建一个仅接受 java.math.BigDecimal 或 Long 的通用 class。这是代码:
class myClass[T]()
{
def display( x : T) = {
println(x.doubleValue())
}
}
val input = new java.math.BigDecimal(100)
// val input = 100L
val x = new myClass[java.math.BigDecimal]()
x.display(input)
显然我会出现这个错误:ScalaFiddle.scala:22: error: value doubleValue is not a member of type parameter T.
我尝试了几个小时的隐式转换、视图绑定和上下文绑定。目前还没有结果。有什么方法可以强制 Scala 相信我 T 有方法 .doubleValue()? (java.big.Decimal 和 Long 都有 .doubleValue() 方法,但它们不共享相同的 super-class)
尝试结构类型绑定
class myClass[T <: {def doubleValue(): Double}]
或输入class
trait HasDoubleValue[T] {
def doubleValue(t: T): Double
}
object HasDoubleValue {
implicit val long: HasDoubleValue[Long] = t => t.doubleValue
implicit val bigDecimal: HasDoubleValue[BigDecimal] = t => t.doubleValue
}
implicit class DoubleValueOps[T: HasDoubleValue](x: T) {
def doubleValue(): Double = implicitly[HasDoubleValue[T]].doubleValue(x)
}
class myClass[T: HasDoubleValue]
在 Dotty (Scala 3) 中,我们可能会使用 union types, for example、
class myClass[T <: (Long | java.math.BigDecimal)]() {
def display(x: T) =
println(
x match {
case t: Long => t.doubleValue
case t: java.math.BigDecimal => t.doubleValue
}
)
}
new myClass().display(new java.math.BigDecimal(100)) // OK
new myClass().display(100L) // OK
new myClass().display("100") // Error
scala> class C private (n: Number) {
| def this(i: Long) = this(i: Number)
| def this(b: BigDecimal) = this(b: Number)
| def d = n.doubleValue
| }
defined class C
scala> new C(42L).d
res0: Double = 42.0
scala> new C(BigDecimal("123456789")).d
res1: Double = 1.23456789E8
或使用类型参数
scala> class C[A <: Number] private (n: A) { def d = n.doubleValue ; def a = n } ; object C {
| def apply(i: Long) = new C(i: Number) ; def apply(b: BigDecimal) = new C(b) }
defined class C
defined object C
我正在尝试创建一个仅接受 java.math.BigDecimal 或 Long 的通用 class。这是代码:
class myClass[T]()
{
def display( x : T) = {
println(x.doubleValue())
}
}
val input = new java.math.BigDecimal(100)
// val input = 100L
val x = new myClass[java.math.BigDecimal]()
x.display(input)
显然我会出现这个错误:ScalaFiddle.scala:22: error: value doubleValue is not a member of type parameter T.
我尝试了几个小时的隐式转换、视图绑定和上下文绑定。目前还没有结果。有什么方法可以强制 Scala 相信我 T 有方法 .doubleValue()? (java.big.Decimal 和 Long 都有 .doubleValue() 方法,但它们不共享相同的 super-class)
尝试结构类型绑定
class myClass[T <: {def doubleValue(): Double}]
或输入class
trait HasDoubleValue[T] {
def doubleValue(t: T): Double
}
object HasDoubleValue {
implicit val long: HasDoubleValue[Long] = t => t.doubleValue
implicit val bigDecimal: HasDoubleValue[BigDecimal] = t => t.doubleValue
}
implicit class DoubleValueOps[T: HasDoubleValue](x: T) {
def doubleValue(): Double = implicitly[HasDoubleValue[T]].doubleValue(x)
}
class myClass[T: HasDoubleValue]
在 Dotty (Scala 3) 中,我们可能会使用 union types, for example、
class myClass[T <: (Long | java.math.BigDecimal)]() {
def display(x: T) =
println(
x match {
case t: Long => t.doubleValue
case t: java.math.BigDecimal => t.doubleValue
}
)
}
new myClass().display(new java.math.BigDecimal(100)) // OK
new myClass().display(100L) // OK
new myClass().display("100") // Error
scala> class C private (n: Number) {
| def this(i: Long) = this(i: Number)
| def this(b: BigDecimal) = this(b: Number)
| def d = n.doubleValue
| }
defined class C
scala> new C(42L).d
res0: Double = 42.0
scala> new C(BigDecimal("123456789")).d
res1: Double = 1.23456789E8
或使用类型参数
scala> class C[A <: Number] private (n: A) { def d = n.doubleValue ; def a = n } ; object C {
| def apply(i: Long) = new C(i: Number) ; def apply(b: BigDecimal) = new C(b) }
defined class C
defined object C