在 Scala 中,什么是“早期初始化程序”?
在 Martin Odersky 的 最近关于 Scala 程序员能力水平的文章中,Expert在库设计者部分,他添加了术语“早期初始化程序”。
Scala 编程中没有提到这些。这些是什么?
In Martin Odersky's recent post about levels of programmer ability in Scala, in the Expert library designer section, he includes the term "early initializers".
These are not mentioned in Programming in Scala. What are they?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
早期初始化程序是子类构造函数的一部分,旨在在其超类之前运行。例如:
如果代码是这样写的
,那么在初始化
Z
时就会出现空指针异常,因为size
是在name
之前初始化的初始化的正常顺序(超类在类之前)。Early initializers are part of the constructor of a subclass that is intended to run before its superclass. For example:
If the code was written instead as
then a null pointer exception would occur when
Z
got initialized, becausesize
is initialized beforename
in the normal ordering of initialization (superclass before class).据我所知,动机(如上面的链接中给出)是:
“当然,当 val 被重写时,它不会被初始化多次。因此,尽管上面示例中的 x2 似乎在每个点都定义了,但这个情况并非如此:在构造超类期间,重写的 val 将显示为 null,抽象 val 也是如此。”
我根本不明白为什么这是自然的。赋值的 rhs 完全有可能产生副作用。请注意,这样的代码结构在 C++ 或 Java 中是完全不可能的(我猜是 Smalltalk,尽管我不能代表该语言)。事实上,您必须通过构造函数在这些语言中隐式进行此类双重赋值...ticilpmi...EXplicit。鉴于 rhs 副作用的不确定性,它看起来真的根本不像一个动机:通过 ASSIGNMENT 回避超类副作用(从而消除超类不变量)的能力?恶心!
允许这种不安全的代码结构是否还有其他“杀手”动机?面向对象语言已经有大约 40 年没有这样的机制了(如果从语言的创建算起,有 30 多年),为什么现在要包含它呢?
这……只是……看起来……很危险。
As far as I can tell, the motivation (as given in the link above) is:
"Naturally when a val is overridden, it is not initialized more than once. So though x2 in the above example is seemingly defined at every point, this is not the case: an overridden val will appear to be null during the construction of superclasses, as will an abstract val."
I don't see why this is natural at all. It is completely possible that the r.h.s. of an assignment might have a side effect. Note that such code structure is completely impossible in either C++ or Java (and I will guess Smalltalk, although I can't speak for that language). In fact you have to make such dual assignments implicit...ticilpmi...EXplicit in those languages via constructors. In the light of the r.h.s. side effect uncertainty, it really doesn't seem like much of a motivation at all: the ability to sidestep superclass side effects (thereby voiding superclass invariants) via ASSIGNMENT? Ick!
Are there other "killer" motivations for allowing such unsafe code structure? Object-oriented languages have done without such a mechanism for about 40 years (30-odd years, if you count from the creation of the language), why include it now?
It...just...seems...dangerous.
转念一想,一年层……
这只是蛋糕。字面上地。
不是早期的任何事情。只是蛋糕(混合)。
Cake 是 The Grand Pooh-bah 自己创造的术语/模式,它采用 Scala 的特征系统,介于类和接口之间。它比Java的装饰模式要好得多。
所谓的“接口”只是一个未命名的基类,而曾经的基类充当了一个特征(坦白说,我不知道可以做到这一点)。我不清楚“with'd”类是否可以接受参数(特征不能),是否会尝试并报告回来。
这个问题及其答案已经成为 Scala 最酷的功能之一。阅读它并感到敬畏。
On second thought, a year layer...
This is just cake. Literally.
Not an early ANYTHING. Just cake (mixins).
Cake is a term/pattern coined by The Grand Pooh-bah himself, one that employs Scala's trait system, which is halfway between a class and an interface. It is far better than Java's decoration pattern.
The so-called "interface" is merely an unnamed base class, and what used to be the base class is acting as a trait (which I frankly did not know could be done). It is unclear to me if a "with'd" class can take arguments (traits can't), will try it and report back.
This question and its answer has stepped into one of Scala's coolest features. Read up on it and be in awe.