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.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.