2013-12-12 3 views
0

В настоящее время я пытаюсь выяснить глубину системы типа Scala и отражения Scala. Я следующий пример кода (мой реальный код является более сложным и имеет смысл, но сводится к этому):Динамическое (вниз) литье в Scala

abstract class Node 
class Foo extends Node 
case class ArrayFoo(var subs : Array[Foo]) extends Foo 
case class IntFoo(i : Integer) extends Foo 

object Main { 
    def DoSomething(node : AnyRef) : AnyRef = { // Fix this function? 
    // do some stuff 
    node 
    } 

    def SetArrayWithReflection(n : Node, a : AnyRef) = { 
    if (a.isInstanceOf[Array[AnyRef]]) { 
     val arrayA = a.asInstanceOf[Array[AnyRef]].map(f => DoSomething(f)) // FIX this call? 
     val getter = n.getClass.getMethods.find(p => p.getName == "subs") 
     val setter = n.getClass.getMethods.find(p => p.getName == "subs_$eq") 
     if (setter == None) println("Method not found!") else { 
     println(f"would need to downcast from ${arrayA.getClass.getComponentType} to ${getter.get.getReturnType.getComponentType}") 
     setter.get.invoke(n, arrayA) // Error happens here 
     } 
    } 
    } 

    def main(args : Array[String]) : Unit = { 
    val my = ArrayFoo(Array(IntFoo(1), IntFoo(2), IntFoo(3))) 
    val newArray = Array(IntFoo(10), IntFoo(20), IntFoo(30)) 
    SetArrayWithReflection(my, newArray) 
    my.subs.foreach(f => println(f)) 
    } 
} 

Выход я получаю:

would need to downcast from class java.lang.Object to class Foo 
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at Main$.SetArrayWithReflection(Main.scala:19) 
    at Main$.main(Main.scala:27) 
    at Main.main(Main.scala) 

Via отражение , Я пытаюсь вызвать метод, ожидающий массив [Object] с массивом [Foo], который, очевидно, должен потерпеть неудачу. Мой вопрос: как я могу опустить или создать подходящий массив для вызова метода? Тот же код действительно работает для списков. Я полагаю, это связано с стиранием типа, которое не происходит в массивах.

Спасибо заранее,

Velines

ответ

1

Вы не можете потупив Array[Object] к Array[Foo]. Самый простой способ для создания массива вам нужно, это

val arrayFoo = Array.ofDim[Foo](arrayA.length) 
System.arraycopy(arrayA, 0, arrayFoo, 0, arrayA.length) 

См System.arraycopy.

Смежные вопросы