Reputation: 185
I have a class which takes a generic as such:
class MyClass[T <: RecordType] (myRecordType: T) {
def doAction() : Unit =
{
myRecordType.someMethod();
}
}
I have a series of subclasses of RecordType that all implement someMethod(). Currently, i call each one individually in my main class as follows:
def main(args: Array[String]): Unit =
{
new MyClass[RecordType10](new RecordType10()).doAction();
new MyClass[RecordType20](new RecordType20()).doAction();
new MyClass[RecordType30](new RecordType30()).doAction();
// many more record types each repeated
}
Ideally, instead of adding a new line for every record type, we would love to have an enumeration of valid record types and just loop through. This way, adding new record types would be as simple as adding to the pre-defined list. But I cannot figure out how to have an Array or Enumeration of class types and then pass those to the instantiation of MyClass. For example, this simple test:
val testClass = classOf(RecordType10);
new MyClass[testClass](new testClass()).doAction();
... it does not compile.
So basic question is: is there a way to have a collection of classes and then iterate through that collection and instantiate another class passing the value for the generic type. Something like this:
val myClasses = Array(classOf(Record10), classOf(Record20), classOf(Record30));
for (theClass <- myClasses)
{
new MyClass[theClass](new theClass()).doAction();
}
Looking forward to any response. Thanks!
Upvotes: 3
Views: 147
Reputation: 2101
Edit: simplified via Alexander's solution to get class names.
This works, but I don't know of a way to build that list automatically (maybe some way through reflection).
trait A {def say = println("Hello")}
class B extends A {override def say = println("Hello B")}
class C extends A {override def say = println("Hello C")}
val ls: List[Class[_ <: A]]= List(classOf[B],classOf[C])
ls.foreach(_.newInstance.say) // prints Hello B, Hello C
Upvotes: 1
Reputation: 853
Using OP's example for simplicity:
object Main {
trait RecordType {
def someMethod()
}
class MyClass[T <: RecordType](myRecordType: T) {
def doAction(): Unit = myRecordType.someMethod()
}
class RecordType10() extends RecordType {
override def someMethod(): Unit = println("some method 10")
}
class RecordType20() extends RecordType {
override def someMethod(): Unit = println("some method 20")
}
def main(args: Array[String]): Unit = {
new MyClass[RecordType10](new RecordType10()).doAction()
new MyClass[RecordType20](new RecordType20()).doAction()
val myClasses = List(classOf[RecordType10], classOf[RecordType20])
for(theClass <- myClasses) {
val instance = theClass.newInstance()
val m = new MyClass(instance)
m.doAction()
}
}
}
Upvotes: 2
Reputation: 3435
It could be simpler:
trait MyType{def myMethod:Unit}
class ActionInvoker[T <: MyType](parameter: T){
def invoke:Unit = parameter.myMethod
}
class Inst1 extends MyType{def myMethod = println("Inst1 here")}
class Inst2 extends MyType{def myMethod = println("Inst2 here")}
val l:List[Class[_ <: MyType]] = List(classOf[Inst1], classOf[Inst2])
for(c <- l){
new ActionInvoker(c.newInstance).invoke
}
Upvotes: 0