0

As we all know, we can initialize a object of template parameter T in C++.

template <typename T>
struct Cont{
    T t;
}

I want to do the same in scala, so I write the following codes. There are some other classes which extends Evaluator, and EvaluateComponent is something like a wrapper. I can write code like new EvaluateComponent[BinaryClassificationEvaluator].evaluate(df)

abstract class Evaluator extends Serializable{
  var predCol = "prediction"
  var trueCol = "label"
  def evaluate(dataset: DataFrame) : String
  def evaluateRDD(dataset: RDD[(Double, Double)]) : String
}

class EvaluateComponent[E <: Evaluator : ClassTag] {
  val evaluator = new E
}

class BinaryClassificationEvaluator extends Evaluator {
  ...
}

However it doesn't compile with error class type required but E found. The post does not solve my question because I want evaluator to be initialized.

1
  • You either must receive the instance of E or a way to construct it. You can not magically create an instance of any arbitrary class. Commented Apr 15, 2020 at 2:19

1 Answer 1

2

The limitation in Scala is the same as Java - generic type is erased at compile time, and no direct access to a class constructor like C++. But it can be done, through Java reflection:

abstract class Evaluator extends Serializable{}

class EvaluateComponent[E <: Evaluator : ClassTag] {
  val evaluator = implicitly[ClassTag[E]].runtimeClass.newInstance().asInstanceOf[E]
}

class BinaryClassificationEvaluator extends Evaluator {}

new EvaluateComponent[BinaryClassificationEvaluator].evaluator // Returns a BinaryClassificationEvaluator

This being said doesn't mean it is a good approach. The takeaways are:

  • The passed class in the generic parameter must have a default constructor. There will be runtime exception if it doesn't
  • Reflection is slower than normal code

Different language program in different mentality. It is better to implement this using type class in Scala but it's another topic.


EDIT:

Class.newInstance is deprecated now. Use Class.getDeclaredConstructor().newInstance() instead

Sign up to request clarification or add additional context in comments.

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.