Как динамически построить подкласс с параметрами на основе строки - PullRequest
0 голосов
/ 23 октября 2019

Код, который у меня есть:

abstract class Animal {
   def init(animalType: String, jsonBlob: String)
}

class Dog (name: String, colour: String) {
   def init(animalType: String, jsonBlob: String) : Unit = {
        name = jsonBlob.name
        colour = jsonBlob.colour
    }
}

class Cat (address: String) {
   def init(animalType: String, jsonBlob: String) : Unit = {
        address = jsonBlob.address
    }
}

То, что я хочу: создать экземпляр Cat или Dog динамически.

Я предпринял попытку с кодом, который выглядит следующим образом:

case class AnimalDefinition(animalType: String, jsonBlob: String)
val animalDefinitions : Array[AnimalDefinition] = // 
val animals : Array[Animal] = animalDefinitions.map(new Animal(_.animalType, _.jsonBlob)) 

Он должен динамически создавать экземпляр правильного класса с помощью параметра animalType. Я думаю, что традиционно я сделал бы это, используя утверждение case (if animalType == "Cat", return new Cat(..)). Но я считаю, что есть автоматический способ сделать это с помощью отражений.

Код не компилируется. Я пытался читать документы по отражению Scala, но у них нет примеров, показывающих динамическое создание экземпляров подклассов с дополнительными параметрами

1 Ответ

1 голос
/ 25 октября 2019

Вы можете заменить

if animalType == "Cat", return new Cat("cat name") ...

на

import scala.reflect.runtime.universe._
val mirror = runtimeMirror(getClass.getClassLoader)
val classSymbol = mirror.staticClass(animalType)
val typ = classSymbol.info
val constructorSymbol = typ.decl(termNames.CONSTRUCTOR).asMethod
val classMirror = mirror.reflectClass(classSymbol)
val constructorMirror = classMirror.reflectConstructor(constructorSymbol)
constructorMirror("cat name").asInstanceOf[Animal]
...