在斯卡拉,什么是“早期初始化”?
在Martin Odersky 最近发表的有关 Scala 程序员能力水平的文章中, 专家库devise者部分中包含了术语“早期初始值” 。
这些在Scala编程中没有提到。 他们是什么?
早期的初始化器是要在其超类之前运行的子类的构造器的一部分。 例如:
abstract class X { val name: String val size = name.size } class Y extends { val name = "class Y" } with X
如果代码被写为
class Z extends X { val name = "class Z" }
那么当Z
被初始化时会发生空指针exception,因为在初始化的正常顺序(在类之前的超类)中, name
被初始化之前, size
被初始化。
据我所知,动机(如上面的链接所示)是:
“自然,当一个val被覆盖的时候,它不会被初始化一次以上,所以虽然上面的例子中的x2看起来是在每个点上定义的,但事实并非如此:在构造超类时,被覆盖的val将显示为null,如同一个抽象的val。“
我不明白为什么这是自然的。 任务的重要性可能有副作用是完全可能的。 请注意,这样的代码结构在C ++或Java中是完全不可能的(我会猜测Smalltalk,尽pipe我不能说那种语言)。 事实上,你必须做出这样的双重任务隐式… ticilpmi …通过构造函数在这些语言中显式。 鉴于rhs副作用的不确定性,它看起来似乎并不是什么动机:通过ASSIGNMENT避开超类副作用(从而排除超类不variables)的能力? 伊克!
有没有其他“杀手”动机允许这样的不安全的代码结构? 面向对象的语言已经有40多年没有这样的机制了(30多年了,如果从创build语言算起),现在为什么要包括它呢?
这……只是……似乎……危险。
第二个想法,一年层…
这只是蛋糕。 从字面上看。
不是早期的任何事情。 只是蛋糕(mixins)。
蛋糕是大维尼自己创造的一个术语/模式,一个使用斯卡拉的特质系统,这是一个阶级和界面之间的中间。 这比Java的装饰模式要好得多。
所谓的“接口”只不过是一个无名的基类,曾经是基类的是作为一个特质(我坦白地不知道可以做到)。 我不清楚,如果一个“with'd”类可以采取参数(特质不能),将尝试它并报告回来。
这个问题及其答案已经成为Scala最酷的function之一。 阅读并敬畏。