[SCALA] 스칼라 : 어떻게 동적 객체와 반사를 사용하여 메서드 Invoke를 인스턴스화합니까?
SCALA스칼라 : 어떻게 동적 객체와 반사를 사용하여 메서드 Invoke를 인스턴스화합니까?
동적 객체와 반사를 사용하여 메서드 Invoke를 인스턴스화에 스칼라에서, 가장 좋은 방법은 무엇입니까?
나는 다음과 같은 자바 코드의 스칼라 환산을하고 싶습니다 :
Class class = Class.forName("Foo");
Object foo = class.newInstance();
Method method = class.getMethod("hello", null);
method.invoke(foo, null);
위의 코드에서 클래스 이름과 메소드 이름을 모두 동적으로 전달됩니다. 자바 위의 메커니즘은 아마 푸 안녕하세요 ()에 사용될 수 있지만, 스칼라 유형은 한 -에 - 하나와 일치하지 않는 자바의 그것과. 예를 들어, 클래스는 단일 개체에 대해 암시 적으로 선언 할 수있다. 또한 스칼라 방법은 기호를 모든 종류의 이름이 될 수 있습니다. 둘 다 이름 맹 글링에 의해 해결된다. 자바와 스칼라 사이에 상호 운용성을 참조하십시오.
천국과 지옥 - 또 다른 문제는 스칼라에서 반사에 설명 된 해결 과부하 및 오토 박싱에 의해 매개 변수의 매칭 될 것으로 보인다.
해결법
-
==============================
1.사용 구조 타이핑 : 자바 반사 메소드를 호출에 의지하지 않고 반사적으로 메소드를 호출 할 수있는 쉬운 방법이있다.
사용 구조 타이핑 : 자바 반사 메소드를 호출에 의지하지 않고 반사적으로 메소드를 호출 할 수있는 쉬운 방법이있다.
필요없는 반사 (물론, 스칼라는 반사 아래를하고있다하지만 우리는 그것을 할 필요가 없습니다) : 그냥 필요한 메소드 서명은 다음 메소드를 호출있는 구조 유형의 객체 참조를 캐스팅.
class Foo { def hello(name: String): String = "Hello there, %s".format(name) } object FooMain { def main(args: Array[String]) { val foo = Class.forName("Foo").newInstance.asInstanceOf[{ def hello(name: String): String }] println(foo.hello("Walter")) // prints "Hello there, Walter" } }
-
==============================
2.난 그냥 하나 개의 스칼라 2.8 실험의 기능을 보완하는 것, 그래서 VonC 월터 장에 의한 대답은 아주 좋다. 사실, 난 그냥 scaladoc을 복사 할 수 있습니다, 그것을 옷을 귀찮게하지 않습니다.
난 그냥 하나 개의 스칼라 2.8 실험의 기능을 보완하는 것, 그래서 VonC 월터 장에 의한 대답은 아주 좋다. 사실, 난 그냥 scaladoc을 복사 할 수 있습니다, 그것을 옷을 귀찮게하지 않습니다.
object Invocation extends AnyRef
class Obj { private def foo(x: Int, y: String): Long = x + y.length }
import scala.reflect.Invocation._ (new Obj) o 'foo(5, "abc") // the 'o' method returns Any val x: Long = (new Obj) oo 'foo(5, "abc") // the 'oo' method casts to expected type.
-
==============================
3.경우 당신은 스칼라 2.10 객체 (클래스가 아닌)의 메소드를 호출 할 필요가 당신은 당신이 이런 식으로 작업을 수행 할 수 있습니다, 문자열 등의 방법 및 개체의 이름을 가지고 :
경우 당신은 스칼라 2.10 객체 (클래스가 아닌)의 메소드를 호출 할 필요가 당신은 당신이 이런 식으로 작업을 수행 할 수 있습니다, 문자열 등의 방법 및 개체의 이름을 가지고 :
package com.example.mytest import scala.reflect.runtime.universe class MyTest object MyTest { def target(i: Int) = println(i) def invoker(objectName: String, methodName: String, arg: Any) = { val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader) val moduleSymbol = runtimeMirror.moduleSymbol( Class.forName(objectName)) val targetMethod = moduleSymbol.typeSignature .members .filter(x => x.isMethod && x.name.toString == methodName) .head .asMethod runtimeMirror.reflect(runtimeMirror.reflectModule(moduleSymbol).instance) .reflectMethod(targetMethod)(arg) } def main(args: Array[String]): Unit = { invoker("com.example.mytest.MyTest$", "target", 5) } }
이 표준 출력에 5를 인쇄합니다. 스칼라 문서에서 더 자세한 사항.
-
==============================
4.instanciation 부분은 매니페스트를 사용할 수 있습니다이 SO의 대답을 참조
instanciation 부분은 매니페스트를 사용할 수 있습니다이 SO의 대답을 참조
class Test[T](implicit m : Manifest[T]) { val testVal = m.erasure.newInstance().asInstanceOf[T] }
class Foo val t = new Test[Foo]
scala> new Test[Set[String]] java.lang.InstantiationException: scala.collection.immutable.Set at java.lang.Class.newInstance0(Class.java:340)
진정한 타입 그래서 안전 솔루션은 공장을 사용하는 것입니다.
참고 :이 스레드에 명시된 바와 같이 매니페스트 여기에 숙박을하지만. "만 사용이 클래스 인스턴스와 같은 유형의 삭제에 대한 액세스를 제공하는 것입니다"지금이다
그런 다음 반사를 통해 방법을 얻을 수 있습니다 :
classOf[ClassName].getMethod("main", classOf[Array[String]])
그것을 호출
scala> class A { | def foo_=(foo: Boolean) = "bar" | } defined class A scala>val a = new A a: A = A@1f854bd scala>a.getClass.getMethod(decode("foo_="), classOf[Boolean]).invoke(a, java.lang.Boolean.TRUE) res15: java.lang.Object = bar
-
==============================
5.@ 네딤의 대답에서 최대 근무, 여기, 전체 응답의 기초 우리가 순진 클래스의 인스턴스를 아래의 주요 차이점은 여기에있는. 이 코드는 여러 생성자의 경우를 처리하고 더 전체 답을 의미하는 것입니다하지 않습니다.
@ 네딤의 대답에서 최대 근무, 여기, 전체 응답의 기초 우리가 순진 클래스의 인스턴스를 아래의 주요 차이점은 여기에있는. 이 코드는 여러 생성자의 경우를 처리하고 더 전체 답을 의미하는 것입니다하지 않습니다.
import scala.reflect.runtime.universe case class Case(foo: Int) { println("Case Case Instantiated") } class Class { println("Class Instantiated") } object Inst { def apply(className: String, arg: Any) = { val runtimeMirror: universe.Mirror = universe.runtimeMirror(getClass.getClassLoader) val classSymbol: universe.ClassSymbol = runtimeMirror.classSymbol(Class.forName(className)) val classMirror: universe.ClassMirror = runtimeMirror.reflectClass(classSymbol) if (classSymbol.companion.toString() == "<none>") // TODO: use nicer method "hiding" in the api? { println(s"Info: $className has no companion object") val constructors = classSymbol.typeSignature.members.filter(_.isConstructor).toList if (constructors.length > 1) { println(s"Info: $className has several constructors") } else { val constructorMirror = classMirror.reflectConstructor(constructors.head.asMethod) // we can reuse it constructorMirror() } } else { val companionSymbol = classSymbol.companion println(s"Info: $className has companion object $companionSymbol") // TBD } } } object app extends App { val c = Inst("Class", "") val cc = Inst("Case", "") }
여기에 컴파일 것 build.sbt입니다 :
lazy val reflection = (project in file(".")) .settings( scalaVersion := "2.11.7", libraryDependencies ++= Seq( "org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided", "org.scala-lang" % "scala-library" % scalaVersion.value % "provided" ) )
from https://stackoverflow.com/questions/1469958/scala-how-do-i-dynamically-instantiate-an-object-and-invoke-a-method-using-refl by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 스칼라에서 널 / 아무것도 / 장치의 용도 (0) | 2019.11.10 |
---|---|
[SCALA] 어떻게 스칼라 변수를 캐스팅 하는가? (0) | 2019.11.10 |
[SCALA] 어떻게 스파크 2.0에서 단위 테스트를 작성하는? (0) | 2019.11.10 |
[SCALA] 어떻게 경우 클래스의 인스턴스를 복제하고 스칼라에 하나의 필드를 변경하려면? (0) | 2019.11.10 |
[SCALA] 어떻게 스칼라 2.9 일에서 "scala.sys.process"는 무엇입니까? (0) | 2019.11.10 |