У меня есть около ста маленьких классов, которые наследуют черту. Классы создаются в фабрике посредством отражения на основе их имен.
Class.forName(name).getConstructor().newInstance().asInstanceOf[Trait]
Теперь требования изменились так, что один и только один из классов должен принимать параметр во время построения. Я пытаюсь изменить фабрику, чтобы справиться с этим новым делом. Рабочий лист REPL с моим подходом выглядит следующим образом:
import java.lang.reflect.Constructor
trait T {
def p: Unit
}
class C1 extends T {
override def p = println("no ymd")
}
class C2(a: Array[String]) extends T {
override def p = println(s"year: ${a(0)}")
}
class C3(a: Array[Int]) extends T {
override def p = println(s"day: ${a(2)}")
}
val ymd = Array("2019","10","23")
val ymd_int = Array(2019,10,23)
def getT(c: Class[_]): T = {
c.getConstructors match {
case Array(c: Constructor[Array[String]]) => c.newInstance(ymd).asInstanceOf[T]
case Array(c: Constructor[Array[Int]]) => c.newInstance(ymd_int).asInstanceOf[T]
case Array(c: Constructor[_]) => c.newInstance().asInstanceOf[T]
case _ => throw new Exception("...")
}
}
getT(classOf[C1]).p
getT(classOf[C2]).p
getT(classOf[C3]).p
В REPL я использую classOf
вместо Class.forName
, потому что имена классов в REPL довольно вялые.
Во время компиляции я получаю предупреждения:
Warning:(25, 23) non-variable type argument Array[String] in type
pattern java.lang.reflect.Constructor[Array[String]] is unchecked
since it is eliminated by erasure
case Array(c: Constructor[Array[String]]) =>
c.newInstance(ymd).asInstanceOf[T]
и
Warning:(26, 23) non-variable type argument Array[Int] in type
pattern java.lang.reflect.Constructor[Array[Int]] is unchecked
since it is eliminated by erasure
case Array(c: Constructor[Array[Int]]) =>
c.newInstance(ymd_int).asInstanceOf[T]
И тогда, конечно, вызовы getT
терпят неудачу, потому что три оператора case выглядят одинаково навремя выполнения, поэтому все три вызова обрабатываются в первом случае.
Пожалуйста, помогите.