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

我知道你可以 间接定义它们 实现与伴侣对象类似的东西 ,但我想知道为什么作为一个语言devise是从类定义退出静态。

OO代表“对象”,而不是类。 面向对象是关于对象或者实例(如果你愿意的话)

静态属性不属于一个对象,它们不能被inheritance,也不参与多态。 简而言之,静态不是面向对象的。

另一方面,Scala 面向对象的。 为了吸引这种语言的开发人员,特别是努力想要像C ++那样努力的Java远不止这些。

它们是C ++发明的,它试图跨越程序和面向对象程序devise的世界,并且需要与C向后兼容。它也出于类似的原因承认了原语。

斯卡拉放弃静态和原始,因为它们是一个程序开发人员需要安抚的时代的遗物。 这些东西没有任何devise良好的语言,希望把自己描述为面向对象。


关于为什么以真正的面向对象为重要,我将无耻地从Bill Venners的邮件列表中复制并粘贴这个片段:

但是,我看到的方式是,单例对象允许您以非常简洁的方式执行需要的静态事物,而且还可以在需要时从inheritance中受益。 一个例子是testing程序的静态部分比较容易,因为你可以对这些部分进行build模,并在各处使用这些特性。 然后在生产程序中使用这些特性的单一对象实现,但在testing中使用模拟实例。

自己不能把它做得更好!

所以如果你想创造一个东西,那么静态和单身都可以完成这个工作。 但是,如果你想让某件事情从某个地方inheritance下来,那么静态对你无能为力。

根据我的经验,你倾向于使用这个能力远远超出你原先想象的那样,特别是在你使用Scala一段时间之后。

我也把这个问题发布在scala用户的谷歌组和比尔·维纳斯之一的“Programming in scala”的回复中有一些见解。

看看这个: https : //groups.google.com/d/msg/scala-user/5jZZrJADbsc/6vZJgi42TIMJ和https://groups.google.com/d/msg/scala-user/5jZZrJADbsc/oTrLFtwGjpEJ

这是一个摘录:

我认为一个目标就是简单一些,把每一个价值作为一个客体,每一个操作都是一个方法。 Java的静态和原语是特殊情况,这使得语言在某种程度上更加“复杂”。

但是我认为另外一个重要的东西是可以将Java静态图映射到Scala(因为Scala需要一些映射到Java静态的互操作的构造),但是从OOinheritance/多态性中受益。 单身物体是真实的物体。 他们可以扩展一个超类或混合的特性,并被传递,但它们本质上也是“静态的”。 事实certificate在实践中非常方便。

还可以看看Martin Odersky的采访(向下滚动到Scala部分的面向对象创新) http://www.artima.com/scalazine/articles/goals_of_scala.html

这是一个摘录:

首先,我们希望成为一个纯粹的面向对象的语言,其中每个值都是一个对象,每一个操作都是一个方法调用,每个variables都是某个对象的成员。 所以我们不需要静力学,但是我们需要一些东西来替代它们,所以我们创build了单体对象的构造。 但即使是单身物体仍然是全球性的结构。 所以挑战是尽可能less地使用它们,因为当你有一个全局结构时,你不能再改变它了。 你不能实例化它。 这是很难testing。 以任何方式修改它是非常困难的。

总结:

从函数式编程的angular度来看,静态成员通常被认为是不好的(见Gilad Bracha这篇文章 – javagenerics之父,主要是因为全局状态而产生的副作用)。 但是scala必须find一种与Java互操作的方式(所以它必须支持静态),并且尽量减less(尽pipe不是完全避免)由于静态而创build的全局状态,scala决定将它们分离成伴随对象。

伴侣对象也具有可扩展的优点,即。 利用inheritance和mixin组合(独立于模拟interop的静态function)。

当我思考静力学如何使事情复杂化时,这些东西就stream进我的脑海:

1)inheritance和多态性需要特殊的规则。 这里是一个例子:

 // This is Java public class A { public static int f() { return 10; } } public class B extends A { public static int f() { return 5; } } public class Main { public static void main(String[] args) { A a = new A(); System.out.println(af()); B b = new B(); System.out.println(bf()); A ba = new B(); System.out.println(ba.f()); } } 

如果你100%确定要打印什么,对你有好处。 我们其他人可以安全地依靠像@Override注释这样强大的工具,这当然是可选的,并且友好的“来自typesA的静态方法f()应该以静态方式访问”警告。 这导致我们

2)获取东西的“静态方式”是一个更加特殊的规则,使事情变得复杂化。

3)静态成员不能是抽象的。 我想你不能拥有一切,对吧?

再次,这些只是几分钟之后我想到的事情而出现的。 我敢打赌,还有其他一些原因,为什么静力学不符合OO范式。

这是真的,静态成员不存在,但是,可以将一个单独的对象关联到每个类:

 class MyClass { } object MyClass { } 

获得类似的结果

面向对象的编程是关于对象及其状态(不接触状态满和无状态的对象)。 我试图强调“静态不属于对象”。 静态字段不能用来表示对象的状态,所以从对象中拉出是合理的。