scala - 如何在 scala 中初始化泛型变量
问题描述
众所周知,我们可以T
在 C++ 中初始化一个模板参数对象。
template <typename T>
struct Cont{
T t;
}
我想在 scala 中做同样的事情,所以我编写了以下代码。还有一些其他类可以扩展Evaluator
,并且EvaluateComponent
类似于包装器。我可以写代码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 {
...
}
但是它不会编译错误class type required but E found
。该帖子没有解决我的问题,因为我希望初始化评估器。
解决方案
Scala 中的限制与 Java 相同——泛型类型在编译时被删除,并且不能直接访问像 C++ 这样的类构造函数。但这可以通过Java反射来完成:
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
话虽这么说,但这并不意味着这是一个好方法。要点是:
- 泛型参数中传递的类必须具有默认构造函数。如果没有,将会有运行时异常
- 反射比普通代码慢
不同的语言程序不同的心态。最好在 Scala 中使用类型类来实现这一点,但这是另一个主题。
编辑:
Class.newInstance
现在已弃用。Class.getDeclaredConstructor().newInstance()
改为使用
推荐阅读
- rest - RESTful 中的“ful”是什么意思?
- xml - 未在 XSLT 中引用默认命名空间
- java - 如何以合理的对齐方式将文本写入 Graphics2D?
- opencl - 了解 OpenCL 中的合并
- reactjs - React Native Animated 缩放图像
- c - free 参数 1 的不兼容类型
- javascript - 安全访问可选流类型的属性
- python-3.x - 如何在本地连接到 azure mongo db?
- python - 在 Tensorflow 中的 batch_norm 层上应用 tf.image.per_image_standardization() 的好处?
- php - PHP 7.2.4 无法连接到我的 MySQL 8.0