为什么Scala在类中没有静态成员?

num*_*ati 50 static scala language-design class static-members

我知道你可以 间接定义它们 与同伴对象实现类似的东西,但我想知道为什么语言设计是从类定义中删除静态.

Kev*_*ght 56

OO中的O代表"对象",而不是类.面向对象是关于对象或实例(如果您愿意)

静态不属于对象,它们不能被继承,它们不参与多态.简而言之,静态不是面向对象的.

另一方面,Scala 面向对象的.远远超过Java,它试图像C++一样特别难以表现,以吸引那些语言的开发人员.

它们是由C++发明的黑客,它正在寻求桥接程序和OO编程的世界,并且需要向后兼容C.它也因类似的原因承认原语.

Scala会删除静态和原语,因为它们是从程序开发人员需要安抚的时候开始的遗留物.这些东西在任何设计良好的语言中都没有,它们希望将自己描述为面向对象.


关于为什么它对真正的OO很重要,我将无耻地复制并粘贴来自Bill Venners的邮件列表上的这个片段:

不过,我看待它的方式是,单例对象允许您以非常简洁的方式执行需要它们的静态事物,但是在需要时也可以从继承中受益.一个例子是测试程序的静态部分更容易,因为你可以制作模拟这些部分的特征并在任何地方使用这些特征.然后在生产程序中使用这些特征的单例对象实现,但在测试中使用模拟实例.

不能自己把它变得更好!

因此,如果你想创造一个东西,那么静力学和单身都可以完成这项工作.但是,如果你想从某个地方继承行为,那么静力学对你没有帮助.

根据我的经验,你倾向于使用这种能力远远超过你原先的想法,特别是在你使用Scala一段时间之后.

  • @Daniel - 这是有争议的,继承在OO中具有相当具体的含义.我将静态描述为被拉入范围,而不是继承.在讨论静态字段而不是静态方法时,差异变得明显.继承的东西也可以被真正覆盖,而不仅仅是被遮蔽. (6认同)
  • 静态方法是继承的,它们不是动态调度的.它们在编译时解决.如何在scala中的对象中定义它们可以帮助你继承或多态 - 你用java的方法说明两个主要的缺点? (2认同)

num*_*ati 16

我还在scala用户google group和Bill Venners上发布了这个问题,其中一篇"Scala编程"的回复有一些见解.

请看一下:https://groups.google.com/d/msg/scala-user/5jZZrJADbsc/6vZJgi42TIMJhttps://groups.google.com/d/msg/scala-user/5jZZrJADbsc/oTrLFtwGjpEJ

这是一段摘录:

我认为一个目标只是简单,通过让每个值都成为一个对象,每个操作都是一个方法调用.Java的静态和原语是特殊情况,这使得语言在某种意义上更"复杂".

但我认为另一个重要的问题是你可以将Java的静态映射到Scala中(因为Scala需要一些映射到Java的静态互操作的构造),但这可以从OO继承/多态中获益.单例对象是真实对象.它们可以扩展超类或混合特征并且可以这样传递,但它们本质上也是"静态的".事实证明这在实践中非常方便.

也看看这个采访马丁·奥德斯基(向下滚动Scala中部分面向对象的创新)http://www.artima.com/scalazine/articles/goals_of_scala.html

这是一段摘录:

首先,我们希望成为一种纯粹的面向对象语言,其中每个值都是一个对象,每个操作都是一个方法调用,每个变量都是某个对象的成员.所以我们不想要静态,但我们需要一些东西来替换它们,所以我们创建了单例对象的构造.但即使是单身对象仍然是全局结构.所以挑战是尽可能少地使用它们,因为当你有一个全局结构时,你就不能再改变它了.你无法实例化它.这很难测试.以任何方式修改它都非常困难.

总结一下:

从功能编程的角度看静态成员通常被认为是不好的(见本职位由吉拉德·布拉彻- Java泛型的父亲主要有副作用,因为全局状态做).但是scala必须找到一种可以与Java互操作的方法(因此它必须支持静态)并最小化(尽管不能完全避免)由于静态而创建的全局状态,scala决定将它们隔离成伴随对象.

伴随对象还具有可扩展的优点,即.利用继承和mixin组合(与为interop模拟静态功能分开).