实例化参数类型的空 object
Instantiating an empty object of parametric type
我正在尝试制作一个 CSV reader,它将带有 header 的 CSV 文件解析为 "line object" 的列表。那些 "line objects" 是函数调用者给定的类型。
我们的想法是能够像这样使用 CSV reader:
case class PlayerData(btag: String, team: String, status: String, role: String)
//...
val p = CSV.from_filename("all-team.test.csv").extract[PlayerData]
for(PlayerData(b, t, _, r) <- p) {
println(s"btag: $b, team: $t, role: $r")
}
我在 extract
函数中实例化 object 时遇到一些问题。目前,函数如下:
class CSV(data: List[List[String]]) {
def make_instance[T: ClassTag]: Option[T] = classTag[T].runtimeClass.newInstance match {
case v: T => Some(v)
case _ => None
}
def get_term[T: TypeTag](term: String) = ru.typeOf[T].decl(ru.TermName(term)).asTerm
def get_mirror[T: ClassTag] = ru.runtimeMirror(classTag[T].runtimeClass.getClassLoader)
def extract[T:ClassTag:TypeTag](): List[T] = {
val header = data.head
val datas = data.tail
data.map(row => {
val res: T = make_instance[T].get
for(i <- 0 to row.length) {
val data_symb = get_term[T](header(i))
val m = get_mirror[T]
val im = m.reflect(res)
val data_mirror = im.reflectField(data_symb)
data_mirror.set(datas(i))
}
res
})
}
}
代码编译通过但在执行过程中出现以下异常:
[error] (run-main-0) java.lang.InstantiationException: CLI$PlayerData
[error] java.lang.InstantiationException: CLI$PlayerData
[error] at java.base/java.lang.Class.newInstance(Class.java:547)
[error] at CSV.make_instance(csv.scala:63)
[error] eam-statat CSV.$anonfun$extract(csv.scala:79)
[error] at scala.collection.immutable.List.map(List.scala:286)
[error] at CSV.extract(csv.scala:78)
[error] at CLI$.main(test.scala:61)
[error] at CLI.main(test.scala)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.base/java.lang.reflect.Method.invoke(Method.java:564)
[error] Caused by: java.lang.NoSuchMethodException: CLI$PlayerData.<init>()
[error] at java.base/java.lang.Class.getConstructor0(Class.java:3302)
[error] at java.base/java.lang.Class.newInstance(Class.java:532)
[error] at CSV.make_instance(csv.scala:63)
[error] at CSV.$anonfun$extract(csv.scala:79)
[error] at scala.collection.immutable.List.map(List.scala:286)
[error] at CSV.extract(csv.scala:78)
[error] at CLI$.main(test.scala:61)
[error] at CLI.main(test.scala)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.base/java.lang.reflect.Method.invoke(Method.java:564)
如何创建我尝试使用 CSV 行填充的 object?
错误在 make_instance
。 classTag[T].runtimeClass.newInstance
尝试调用 T
即 PlayerData
的零参数构造函数。而 PlayerData
没有这样的构造函数。所以要么将这样的构造函数添加到 PlayerData
case class PlayerData(btag: String, team: String, status: String, role: String) {
def this() = {
this("", "", "", "")
}
}
或修复make_instance
调用正确的构造函数
def make_instance[T: ClassTag]: Option[T] = classTag[T].runtimeClass.getConstructor(classOf[String],classOf[String],classOf[String],classOf[String]).newInstance("", "", "", "") match {
case v: T => Some(v)
case _ => None
}
(当然这是特定于 PlayerData
,而不是任意 T
)
对于任意 T
你应该修改 make_instance
class CSV(data: List[List[String]]) {
//def make_instance[T: ClassTag]: Option[T] =
def make_instance[T: ClassTag](args: Seq[String]): Option[T] =
// classTag[T].runtimeClass.newInstance match {
classTag[T].runtimeClass.getConstructor(Seq.fill(args.length)(classOf[String]): _*).newInstance(args: _*) match {
case v: T => Some(v)
case _ => None
}
def get_term[T: TypeTag](term: String) = ru.typeOf[T].decl(ru.TermName(term)).asTerm
def get_mirror[T: ClassTag] = ru.runtimeMirror(classTag[T].runtimeClass.getClassLoader)
def extract[T:ClassTag:TypeTag](): List[T] = {
val header = data.head
val datas = data.tail
/*data*/datas.map(row => {
val res: T = /*make_instance[T].get*/make_instance[T](row).get
for(i <- 0 /*to*/until row.length) {
val data_symb = get_term[T](header(i))
val m = get_mirror[T]
val im = m.reflect(res)
val data_mirror = im.reflectField(data_symb)
data_mirror.set(/*datas*/row(i))
}
res
})
}
}
case class PlayerData(btag: String, team: String, status: String, role: String)
val p = new CSV(List(
List("btag", "team", "status", "role"),
List("a", "b", "c", "d"),
List("a1", "b1", "c1", "d1")
)).extract[PlayerData]
for(PlayerData(b, t, _, r) <- p) {
println(s"btag: $b, team: $t, role: $r")
}
//btag: a, team: b, role: d
//btag: a1, team: b1, role: d1
我正在尝试制作一个 CSV reader,它将带有 header 的 CSV 文件解析为 "line object" 的列表。那些 "line objects" 是函数调用者给定的类型。
我们的想法是能够像这样使用 CSV reader:
case class PlayerData(btag: String, team: String, status: String, role: String)
//...
val p = CSV.from_filename("all-team.test.csv").extract[PlayerData]
for(PlayerData(b, t, _, r) <- p) {
println(s"btag: $b, team: $t, role: $r")
}
我在 extract
函数中实例化 object 时遇到一些问题。目前,函数如下:
class CSV(data: List[List[String]]) {
def make_instance[T: ClassTag]: Option[T] = classTag[T].runtimeClass.newInstance match {
case v: T => Some(v)
case _ => None
}
def get_term[T: TypeTag](term: String) = ru.typeOf[T].decl(ru.TermName(term)).asTerm
def get_mirror[T: ClassTag] = ru.runtimeMirror(classTag[T].runtimeClass.getClassLoader)
def extract[T:ClassTag:TypeTag](): List[T] = {
val header = data.head
val datas = data.tail
data.map(row => {
val res: T = make_instance[T].get
for(i <- 0 to row.length) {
val data_symb = get_term[T](header(i))
val m = get_mirror[T]
val im = m.reflect(res)
val data_mirror = im.reflectField(data_symb)
data_mirror.set(datas(i))
}
res
})
}
}
代码编译通过但在执行过程中出现以下异常:
[error] (run-main-0) java.lang.InstantiationException: CLI$PlayerData
[error] java.lang.InstantiationException: CLI$PlayerData
[error] at java.base/java.lang.Class.newInstance(Class.java:547)
[error] at CSV.make_instance(csv.scala:63)
[error] eam-statat CSV.$anonfun$extract(csv.scala:79)
[error] at scala.collection.immutable.List.map(List.scala:286)
[error] at CSV.extract(csv.scala:78)
[error] at CLI$.main(test.scala:61)
[error] at CLI.main(test.scala)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.base/java.lang.reflect.Method.invoke(Method.java:564)
[error] Caused by: java.lang.NoSuchMethodException: CLI$PlayerData.<init>()
[error] at java.base/java.lang.Class.getConstructor0(Class.java:3302)
[error] at java.base/java.lang.Class.newInstance(Class.java:532)
[error] at CSV.make_instance(csv.scala:63)
[error] at CSV.$anonfun$extract(csv.scala:79)
[error] at scala.collection.immutable.List.map(List.scala:286)
[error] at CSV.extract(csv.scala:78)
[error] at CLI$.main(test.scala:61)
[error] at CLI.main(test.scala)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.base/java.lang.reflect.Method.invoke(Method.java:564)
如何创建我尝试使用 CSV 行填充的 object?
错误在 make_instance
。 classTag[T].runtimeClass.newInstance
尝试调用 T
即 PlayerData
的零参数构造函数。而 PlayerData
没有这样的构造函数。所以要么将这样的构造函数添加到 PlayerData
case class PlayerData(btag: String, team: String, status: String, role: String) {
def this() = {
this("", "", "", "")
}
}
或修复make_instance
调用正确的构造函数
def make_instance[T: ClassTag]: Option[T] = classTag[T].runtimeClass.getConstructor(classOf[String],classOf[String],classOf[String],classOf[String]).newInstance("", "", "", "") match {
case v: T => Some(v)
case _ => None
}
(当然这是特定于 PlayerData
,而不是任意 T
)
对于任意 T
你应该修改 make_instance
class CSV(data: List[List[String]]) {
//def make_instance[T: ClassTag]: Option[T] =
def make_instance[T: ClassTag](args: Seq[String]): Option[T] =
// classTag[T].runtimeClass.newInstance match {
classTag[T].runtimeClass.getConstructor(Seq.fill(args.length)(classOf[String]): _*).newInstance(args: _*) match {
case v: T => Some(v)
case _ => None
}
def get_term[T: TypeTag](term: String) = ru.typeOf[T].decl(ru.TermName(term)).asTerm
def get_mirror[T: ClassTag] = ru.runtimeMirror(classTag[T].runtimeClass.getClassLoader)
def extract[T:ClassTag:TypeTag](): List[T] = {
val header = data.head
val datas = data.tail
/*data*/datas.map(row => {
val res: T = /*make_instance[T].get*/make_instance[T](row).get
for(i <- 0 /*to*/until row.length) {
val data_symb = get_term[T](header(i))
val m = get_mirror[T]
val im = m.reflect(res)
val data_mirror = im.reflectField(data_symb)
data_mirror.set(/*datas*/row(i))
}
res
})
}
}
case class PlayerData(btag: String, team: String, status: String, role: String)
val p = new CSV(List(
List("btag", "team", "status", "role"),
List("a", "b", "c", "d"),
List("a1", "b1", "c1", "d1")
)).extract[PlayerData]
for(PlayerData(b, t, _, r) <- p) {
println(s"btag: $b, team: $t, role: $r")
}
//btag: a, team: b, role: d
//btag: a1, team: b1, role: d1