基础课程
abstract class BaseSourceReader[T <: BaseSource] {
/**
* Method to read data from source
*/
def readFromSource(identifier: T): Seq[String]
}
// Trait common to all source identifiers
trait BaseSource
派生类
class XYZSourceReader(param1: String) extends BaseSourceReader[XYZBaseSource] {
override def readFromSource(identifier: XYZBaseSource): Seq[String] =
// some implementation
}
case class XYZBaseSource(
paramA: String,
paramB: Seq[String]) extends BaseSource
现在我想做的是将基础源阅读器注入泛型类,使实现独立于源:
class MySourceTrasformerJob(
val sourceReader: BaseSourceReader[BaseSource]) {
// some code
}
并像这样使用它:
class MyTransformerJobApp {
val reader = new XYZSourceReader(param)
val job = MySourceTrasformerJob(reader)
}
要使此代码段生效,编译器会建议class SourceReader is invariant in type T. You may wish to define T as +T instead. (SLS 4.5)
我尝试更新BaseSourceReader
:
- abstract class BaseSourceReader[T <: BaseSource] {
+ abstract class BaseSourceReader[+T <: BaseSource] {
但是导致readFromSource
方法错误出错:协变类型T出现在值标识符类型T的逆变位置。
我发现一个有效的解决方案是将实现与源头绑定,但不是&#34;泛型&#34;足够的实施:
class MySourceTrasformerJob(
val sourceReader: BaseSourceReader[XYZBaseSource]) {
// some code
}
我有点陷入这个循环并尝试模型更新,任何建议的方法来处理这个但是肯定坚持通用的抽象类依赖注入?
答案 0 :(得分:2)
如果你的类型既需要同时也不是协变(或逆变),你就可以解决这个问题。(这是不可能实现的。在这种情况下你所能做的就是让它保持不变你可以通过重写这样的MySourceTransformerJob
来避免这种情况:
case class MySourceTransformerJob[T <: BaseSource](sourceReader: BaseSourceReader[T])
我做了这个,没有进一步修改你的代码编译。
这也是表达意图的更自然的方式。毕竟,您正在设计BaseSourceReader[T <: BaseSource]
在T
类型中具有下限的泛型。因此MySourceTransformerJob
最好在T
上要求同样的要求,如果它不是设计上对它有任何限制。