Scala转换为泛型类型(用于泛型数值函数)
我试图实现一个封装数学Java函数的通用函数。为了简单起见,我们可以假设Java函数(Java7)接受一个参数并返回一个结果,两种类型都是Java.lang.Double。当然,包装函数应该包含一个参数和一个结果,这两个参数和结果都是泛型的,但都是数字类型a。问题是我无法在包装函数中将结果转换回类型a。哪里出了问题 注:(我是Scala的新手,使用以下参考资料解决了这个问题。)Scala转换为泛型类型(用于泛型数值函数),scala,generics,casting,scala-java-interop,Scala,Generics,Casting,Scala Java Interop,我试图实现一个封装数学Java函数的通用函数。为了简单起见,我们可以假设Java函数(Java7)接受一个参数并返回一个结果,两种类型都是Java.lang.Double。当然,包装函数应该包含一个参数和一个结果,这两个参数和结果都是泛型的,但都是数字类型a。问题是我无法在包装函数中将结果转换回类型a。哪里出了问题 注:(我是Scala的新手,使用以下参考资料解决了这个问题。) 我使用隐式类型trait Numeric来强制执行模板类型是数值的 我发现了“import scala.collec
- 我使用隐式类型trait Numeric来强制执行模板类型是数值的李>
- 我发现了“import scala.collection.JavaConversions.”,我并不完全理解,但在我看来,这是为了转换Java集合,并不能解决我的问题,是吗李>
- 正如这里所描述的,我试图使用Manifest强制执行正确的强制转换(变体B),但最终导致异常java.lang.ClassCastException李>
Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105)
at test.mytest$.main(test.scala:10)
at test.mytest.main(test.scala)
3.0
int
“一些代码”A2
输出:
Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105)
at test.mytest$.main(test.scala:10)
at test.mytest.main(test.scala)
3.0
int
“一些代码”A3
输出:
Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105)
at test.mytest$.main(test.scala:10)
at test.mytest.main(test.scala)
3.0
int
变体B
输出:
(对于变体A1、A2和A3的等价物也是如此,因为异常现在在函数f的第6行中抛出。)
无论如何,您不能将
Double
强制转换为Integer
(因为它已装箱)Numeric
只允许您在T上进行一组数学运算(通过import num.
),无需其他操作(不需要中间类型)。A2只起作用,因为println由于f(3)
而期望Any
,因此T
自动推断为Any
println(f[Int](3))
永远不起作用,f[Any](3)
永远起作用
如果您想要实现操作Double的泛型函数(只有当您有特定于Double的操作时,才可能需要该函数),那么最好返回Double。如果不能,则必须通过分析t来手动构造类型:
def f[A](x: A)(implicit num: Numeric[A]): A = {
val result = new java.lang.Double(num.toDouble(x))
(x match {
case x: Double => result
case x: Int => result.toInt
case x: Float => result.toFloat
case x: Long => result.toLong
}).asInstanceOf[A]
}
不能在这里执行[A]的原因是A已经装箱了@specialized
注释不适用于的安装()
更新:实际上,@specialized
工作:
def f[@specialized(Int, Double, Long, Float) A](x: A)(implicit num: Numeric[A]): A = {
val result = new java.lang.Double(num.toDouble(x))
result.doubleValue.asInstanceOf[A]
}
但是它-所以要小心
p.S.清单不推荐使用:改用classTag
/typeTag
是否有可能强制强制强制将双精度转换为整数,如在Java中,例如(int)(1.8)返回1?尽管如此,匹配输入参数对我来说是可行的,但这有点像黑客攻击——从我的角度来看——如果能得到语言本身的支持就好了,因为这样变体B就可以工作了,是吗?非常感谢,对我来说,它现在可以工作了!:)<代码>(1.8)。asInstanceOf[Int]
在scala中工作,但它不适用于盒装类型(即使在Java中),这太棒了!更新后的解决方案现在使用了语言功能,正如我所期望的那样:该解决方案现在是“真正”通用的,因为如果列表为空,前一个解决方案对于函数def[a](list:list[a])(implicit num:Numeric[a]):a={…}
就不起作用(或者至少需要另一种解决方法)。谢谢+1用于更新的解决方案。