динамически создавать класс в Scala, я должен использовать интерпретатор? - PullRequest
12 голосов
/ 02 мая 2010

Я хочу создать класс во время выполнения в Scala . А пока рассмотрим простой случай, когда я хочу сделать эквивалент java bean-компонента с некоторыми атрибутами, я знаю эти атрибуты только во время выполнения.

Как мне создать класс scala? Я готов создать из исходного файла scala, если есть способ скомпилировать и загрузить его во время выполнения, я могу захотеть, поскольку иногда у меня есть какая-то сложная функция, которую я хочу добавить в класс. Как я могу это сделать?

Я беспокоюсь, что интерпретатор scala, о котором я читал, помещает в песочницу интерпретируемый код, который он загружает, чтобы он не был доступен общему приложению, в котором находится интерпретатор? Если это так, то я не смог бы использовать динамически загружаемый класс scala.

В любом случае, вопрос заключается в том, как я могу динамически создать класс scala во время выполнения и использовать его в своем приложении, в лучшем случае это загрузить его из исходного файла scala во время выполнения, что-то вроде interpreterSource("file.scala") и загрузить его в моей текущей среде выполнения второй лучший случай - это создание с помощью вызова методов , т. е. createClass(...), чтобы создать его во время выполнения.

Спасибо, Фил

1 Ответ

7 голосов
/ 02 мая 2010

Недостаточно информации, чтобы узнать лучший ответ, но помните, что вы работаете на JVM, поэтому любые методы или библиотеки байт-кода, допустимые для Java, также должны быть здесь действительны.методов, которые вы можете использовать, но лучший выбор полностью зависит от вашего конкретного случая использования, так как многие из них не общего назначения.Вот несколько идей:

  • Для простого компонента вы также можете просто использовать карту или заглянуть в класс DynaBean с помощью Apache Commons.

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

  • Анализатор иКастомные DSL хорошо подходят в некоторых случаях.Как и сценарии оболочки бобов.

Посмотрите видео о ScalaDays здесь: http://days2010.scala -lang.org / node / 138/146 , демонстрирующее использование Scalaкак язык сценариев, совместимый с JSR-223.Это должно охватывать большинство сценариев, в которых вы хотите оценить Scala во время выполнения.

Вы также можете посмотреть ветку электронной почты здесь: http://scala -programming-language.1934581.n4.nabble.com/Compiler-API-td1992165.html#a1992165

Содержит следующий пример кода:

// We currently call the compiler directly 
// To reduce coupling, we could instead use ant and the scalac ant task 

import scala.tools.nsc.{Global, Settings} 
import scala.tools.nsc.reporters.ConsoleReporter
{ 
  // called in the event of a compilation error 
  def error(message: String): Nothing = ... 

  val settings = new Settings(error) 
  settings.outdir.value = classesDir.getPath 
  settings.deprecation.value = true // enable detailed deprecation warnings 
  settings.unchecked.value = true // enable detailed unchecked warnings 

  val reporter = new ConsoleReporter(settings) 

  val compiler = new Global(settings, reporter) 
  (new compiler.Run).compile(filenames) 

  reporter.printSummary 
  if (reporter.hasErrors || reporter.WARNING.count > 0) 
  { 
             ... 
  } 
} 


val mainMethod: Method = { 
  val urls = Array[URL]( classesDir.toURL ) 

  val loader = new URLClassLoader(urls) 

  try { 
    val clazz: Class = loader.loadClass(...) 

    val method: Method = clazz.getMethod("main", Array[Class]( classOf[Array[String]] )) 
    if (Modifier.isStatic(method.getModifiers)) { 
       method 
    } else { 
      ... 
    } 
  } catch { 
    case cnf: ClassNotFoundException => ... 
    case nsm: NoSuchMethodException => ... 
  } 
} 

mainMethod.invoke(null, Array[Object]( args )) 
...