扩展类,在子类体中定义函数参数?除非通过名称声明参数,否则超级构造函数不能传递自引用

时间:2017-02-05 21:22:30

标签: scala

1)考虑以下示例:

trait Fuel
trait Flow extends Fuel
trait Gas extends Fuel

trait CarbonDioxide

abstract class Car[I, O](engine: I => O) {
  def run(fuel: Fuel): O = {
    engine(fuel)
  }
}

object Electric extends Car[Flow, Unit]((flow: Flow) => ())
object Petrol extends Car[Gas, CarbonDioxide]((gas: Gas) => new CarbonDioxide {})

我不想直接在构造函数中声明engine: I => O函数,而是希望在Petrol的主体中定义一个(更复杂的)方法,如下所示:

object Petrol extends Car[Gas, CarbonDioxide](Petrol.run) {

  def run(gas: Gas): CarbonDioxide =
  {
    new CarbonDioxide {}
  }
}

现在这在我的IDE中看起来没问题,但编译器说:

  

超级构造函数不能传递自引用,除非参数是按名称声明的

我怎样才能克服这个?

2)如果在我的代码中某处我这样做:

val fuelCars = Map(
  "Flow" -> Electric,
  "Gas" -> Petrol
)

println(fuelCars("Flow").run(new Flow{})

代码

object Petrol extends Car[Gas, CarbonDioxide]((gas: Gas) => new CarbonDioxide {})有效,但只要我用run将其更改为第二个版本,我就会

  

无法使用此类签名解析参考运行

但为什么?

1 个答案:

答案 0 :(得分:2)

超类是在子类之前构造的,因此你不能将构造函数参数从尚未构造的子传递给super。

也许您能做的最好的事情是为engine参数提供虚拟代码(它是私有的,不能被覆盖),然后覆盖引用engine参数的任何/所有代码

abstract class Car[I, O](engine: I => O) {
  def run(fuel: I): O = engine(fuel)
}

object Petrol extends Car[Gas, CarbonDioxide](_ => new CarbonDioxide{}) {
                           // dummy code here ^^^^^^^^^^^^^^^^^^^^^^^//
  override def run(gas: Gas): CarbonDioxide = {/* real replacement code here*/}
}