在Martin Odersky最近关于Scala中程序员能力水平的帖子中,在Expert库设计器部分中,他包括了“早期初始化程序”一词。。
这些在Scala编程中没有提到。这些是什么?
在Martin Odersky最近关于Scala中程序员能力水平的帖子中,在Expert库设计器部分中,他包括了“早期初始化程序”一词。。
这些在Scala编程中没有提到。这些是什么?
Answers:
早期的初始化程序是打算在其超类之前运行的子类的构造函数的一部分。例如:
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
初始化时会发生空指针异常,这size
是因为初始化是按照初始化name
的常规顺序进行的(类之前的超类)。
def nameInit: String; val name = nameInit
(被覆盖)更可取def nameInit = "foo"
?
def
将被类的方法表覆盖,从而保证将执行最特定的版本,而val
初始化没有这样的东西-被覆盖的是吸气剂,而不是初始化。
据我所知,动机(如上面的链接所示)是:
“自然地,当一个val被覆盖时,它不会被多次初始化。因此,尽管上面的示例中的x2似乎在每个点上都定义了,但事实并非如此:在构建超类时,被覆盖的val似乎为空,以及抽象val。”
我不明白为什么这是自然的。分配的rhs完全可能有副作用。请注意,无论在C ++还是Java中,这样的代码结构都是完全不可能的(我会猜测Smalltalk,尽管我不能说那种语言)。实际上,您必须通过构造函数在这些语言中隐式... ticilpmi ... EXPICTIVE这样的双重分配。鉴于rhs副作用的不确定性,这实际上似乎根本不是什么动机:通过ASSIGNMENT避开超类副作用(从而使超类不变式无效)的能力吗?ck!
是否还有其他“杀手级”动机允许这种不安全的代码结构?面向对象的语言在没有这种机制的情况下已经使用了大约40年(如果从创建语言的时间算起,大约30多年),为什么现在要包含它呢?
只是……似乎……很危险。
再三考虑,一年层……
这只是蛋糕。从字面上看。
不算早。只是蛋糕(mixins)。
Cake是由The Pooh-bah本人创造的一个术语/模式,它采用Scala的特征系统,该系统位于类和界面之间。它远比Java的修饰样式好。
所谓的“接口”仅是一个未命名的基类,而以前作为基类的是作为特征(我坦率地不知道可以做到)。我不清楚“ withd”类是否可以接受参数(特征不能接受),是否可以尝试并进行报告。
这个问题及其答案已进入Scala最酷的功能之一。阅读它,敬畏。
ClassTemplate ::= [EarlyDefs] ClassParents [TemplateBody]
,ClassParents ::= Constr {'with' AnnotType}
和Constr ::= AnnotType {'(' [Exprs] ')'}
,我会说,“with'd”类可以带参数。