在以下代码中,为什么我可以返回Array[A]
而不是A
?如何退回A
?
scala> import scala.reflect._
import scala.reflect._
scala> class Covariant[+A]{
| def m[A:ClassTag]:Array[A] = new Array[A](1)
| }
defined class Covariant
scala> class Covariant[+A]{
| def m[A:ClassTag]:A = new A
| }
<console>:15: error: class type required but A found
def m[A:ClassTag]:A = new A
^
答案 0 :(得分:2)
问题来自于没有默认构造函数的类(即没有参数)。例如,您无法创建
的实例case class IntWrapper(value:Int)
没有提供一些Int
值。此外,在Scala中没有办法表达类型必须具有这样的构造函数的约束。因此,Scala编译器无法为new A
生成任何有效代码。它适用于数组,因为所有数组都具有相同的形状,即所有数组都有一个只有一个Int
参数的构造函数,因此编译器可以在这里生成一个有效的调用。
您可以使用的最佳解决方法是使用默认构造函数为类型创建自己的类型类:
trait DefaultConstructor[A] {
def create(): A
}
class Covariant[+A] {
def m[A](implicit ctr:DefaultConstructor[A]): A = ctr.create()
}
答案 1 :(得分:0)
嗯......答案很简单,你在这两个例子中做了不同的事情,
如果您尝试在Array
示例
scala> import scala.reflect._
// import scala.reflect._
scala> def m[A:ClassTag]:Array[A] = List(new A).toArray
// <console>:16: error: class type required but A found
// def m[A:ClassTag]:Array[A] = List(new A).toArray
// ^
scala> def m[A:ClassTag]:A = new A
// <console>:16: error: class type required but A found
// def m[A:ClassTag]:A = new A
// ^
如果你想让它发挥作用。您需要从TypeTag
证据
import scala.reflect._
def createNewInstance[A: ClassTag] = {
val clazz = classOf[A]
val constructors = clazz.getConstructors
val defaultConstructor = constructors(0)
val instance = defaultConstructor.newInstance()
instance.asInstanceOf[A]
}
def m[A:ClassTag]: Array[A] = List(createNewInstance[A]).toArray
def m[A:ClassTag]: A = createNewInstance[A]
答案 2 :(得分:0)
new 关键字用于创建类的新实例。由于Array是一个有效的类 new Array [A](1)是一个有效的语句。但是, new A 无效,因为A不是有效的类类型(错误已经表明)。因此编译时错误。
我不确定,您想要做什么,但要返回A类结果,您只需使用以下代码:
def m[A:ClassTag](a:A) = a