使用抽象类

时间:2017-07-12 20:58:40

标签: scala

基础课程

 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
 }

我有点陷入这个循环并尝试模型更新,任何建议的方法来处理这个但是肯定坚持通用的抽象类依赖注入?

1 个答案:

答案 0 :(得分:2)

如果你的类型既需要同时也不是协变(或逆变),你就可以解决这个问题。(这是不可能实现的。在这种情况下你所能做的就是让它保持不变你可以通过重写这样的MySourceTransformerJob来避免这种情况:

case class MySourceTransformerJob[T <: BaseSource](sourceReader: BaseSourceReader[T])

我做了这个,没有进一步修改你的代码编译。 这也是表达意图的更自然的方式。毕竟,您正在设计BaseSourceReader[T <: BaseSource]T类型中具有下限的泛型。因此MySourceTransformerJob最好在T上要求同样的要求,如果它不是设计上对它有任何限制。