Подтвердить что ты не робот

Динамически создавать класс в scala, следует ли использовать интерпретатор?

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

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

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

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

Спасибо, Фил

4b9b3361

Ответ 1

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

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

  • Для простого bean вы можете также просто используйте карту или посмотрите на Класс DynaBean из сообщества apache.

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

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

Посмотрите видео 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 ))