3

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!

1

3 Answers 3

2

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()
    }
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for using original example...clear and brilliant!
1

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

1 Comment

if you provide a specific type in the list declaration then you will also not need to cast with asInstanceof[A]
0

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
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.