Można to zrobić z refleksji w Javie:
class A {
def cat(s1: String, s2: String) = s1 + " " + s2
}
val a = new A
val hi = "Hello"
val all = "World"
val method = a.getClass.getMethod("cat",hi.getClass,all.getClass)
method.invoke(a,hi,all)
A jeśli ma to być łatwe w Scala można dokonać klasy, która robi to za Ciebie, plus niejawna do konwersji:
case class Caller[T>:Null<:AnyRef](klass:T) {
def call(methodName:String,args:AnyRef*):AnyRef = {
def argtypes = args.map(_.getClass)
def method = klass.getClass.getMethod(methodName, argtypes: _*)
method.invoke(klass,args: _*)
}
}
implicit def anyref2callable[T>:Null<:AnyRef](klass:T):Caller[T] = new Caller(klass)
a call ("cat","Hi","there")
Tego typu rzeczy przekształcają błędy w czasie kompilacji w błędy środowiska wykonawczego (tzn. W zasadzie omijają system typów), więc należy ich używać z rozwagą.
(Edit. I zobaczyć wykorzystanie NameTransformer w link powyżej - dodając, że pomoże, jeśli spróbujesz użyć operatorów)
Dostaję błąd na poniższych 'List (1, 2) wezwanie ("wziąć", 1)' 'Błąd jest typ. niedopasowanie; znalezione: Int (1) wymagane: AnyRef Uwaga: niejawny istnieje od scala.Int => java.lang.Integer, ale metody odziedziczone z Object są renderowane niejednoznacznie, aby uniknąć niejawnego, który przekształci dowolną scala .Int wszelkich AnyRef.Możesz chcieć użyć typu ascription: x: java.lang.Integer. "Czy istnieje sposób obsługi typów pierwotnych? (Chcę dynamicznie generować listę argumentów ... może być lista 'Dowolny') – dips
@dips - Możesz' .asInstanceOf [AnyRef] 'po drodze (działa również z' Any') lub '1: java.lang.Integer', jak sugeruje błąd, lub możesz dopasować prymitywy i postępuj indywidualnie, jeśli naprawdę tego potrzebujesz, choć nie musisz tego tutaj robić. –
Dzięki! Tak więc mój podpis funkcji 'call' teraz przyjmuje' args: Any * 'i zamieniam go na' AnyRef * 'w ciele' call' jako 'args map {_.asInstanceOf [AnyRef]}'. Mam nadzieję, że to w porządku. Nie znam subtelności, stąd pytanie. – dips