为什么我可以使用Classtag返回数组[A]而不是A?我该怎么回A?

时间:2017-12-11 16:28:12

标签: scala

在以下代码中,为什么我可以返回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
                                 ^

3 个答案:

答案 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