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
将其更改为第二个版本,我就会
无法使用此类签名解析参考运行
但为什么?
答案 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*/}
}