Reputation: 2965
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.
Upvotes: 0
Views: 481
Reputation: 15304
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:
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
Upvotes: 2