为什么单例对象更面向对象?

在Scala编程:一个全面的分步指南 ,作者说:

Scala比Java更面向对象的一种方式是Scala中的类不能有静态成员。 相反,斯卡拉有单身的对象。

为什么单例对象更面向对象? 什么是不使用静态成员,但单身人士的对象?

试图“大局面”; 其他大部分内容已经被其他答案所覆盖,但似乎并没有一个全面的答复,把所有的答案放在一起,并join了点。 所以这里…

类上的静态方法不是对象的方法,这意味着:

  1. 静态成员不能从父类/特征inheritance
  2. 静态成员不能用来实现一个接口
  3. 一个类的静态成员不能作为parameter passing给某个函数

    (因为以上几点…)

  4. 静态成员不能被覆盖
  5. 静态成员不能是多态的

对象的要点是它们可以inheritance父对象,实现接口,并作为parameter passing – 静态成员没有这些属性,所以它们不是真正的面向对象的,它们只不过是一个命名空间而已。

另一方面,单一对象是对象社区的完全成员。


单身人士的另一个非常有用的特性是,他们可以很容易地在稍后的时间点改变,而不是单身人士,如果你从静态方法开始,这是一个特别痛苦的重构。

想象一下,您devise了一个打印地址的程序,并通过某些类的静态方法来表示与打印机的交互,之后您希望能够添加另一台打印机,并允许用户select要使用的打印机。不是一个有趣的经验!

单例对象的行为类似于它们可以扩展/实现其他types。

不能在Java中用静态类来做到这点 – 它使用getInstance (至less)允许更好的命名空间/稳定标识符来隐藏区别,这与Java单例模式 相当

提示:这就是所谓的面向对象的编程。

认真。

也许我错过了一些根本上重要的东西,但我没有看到什么大惊小怪:对象比非对象更面向对象,因为它们是对象。 这真的需要解释吗?

注意:虽然听起来确实如此 ,但我并不想在这里听起来很自鸣。 我看了所有其他的答案,我发现他们非常混乱。 对我来说,很明显的是对象和方法比命名空间和过程(这是静态的“方法”实际上是什么)更“面向对象”的定义更加面向对象。

使用单例对象的另一种方法是将类本身作为对象,例如Ruby,Python,Smalltalk,Newspeak等。

对于静态成员,没有任何对象 。 这个类真的只是一个命名空间。

在一个单例中,总是有至less一个对象。

老实说,这是分裂的头发。

在给定一个Scala类的意义上,它更多是面向对象的,每个方法调用都是对该对象的方法调用。 在Java中,静态方法不与对象状态交互。

实际上,给定一个静态方法m()的类A的对象,调用am()被认为是不好的做法。 相反,build议调用Am() (我相信Eclipse会给你一个警告)。 Java静态方法不能被覆盖,只能通过其他方法隐藏:

 class A { public static void m() { System.out.println("m from A"); } } public class B extends A { public static void m() { System.out.println("m from B"); } public static void main(String[] args) { A a = new B(); am(); } } 

我将am()打印什么?

在Scala中,你可以将静态方法放在同伴对象A和B中,而且你的意图会更清楚,因为你明确地指向了同伴A或B.

在Scala中添加相同的示例:

 class A object A { def m() = println("m from A") } class B extends A object B { def m() = println("m from B") def main(args: Array[String]) { val a = new B Am() // cannot call am() } } 

在一些情况下可能有一些差异。 在Java中,你不能重载静态方法,所以如果你有静态方法的类,你将无法自定义和覆盖其部分行为。 如果你使用单例对象,你可以插入从子类创build的单例。

这是一个营销的东西,真的。 考虑两个例子:

 class foo static const int bar = 42; end class class superfoo Integer bar = ConstInteger.new(42); end class 

那么这里有什么可观察的区别呢?

  • 在一个行为良好的语言中,创build的附加存储是相同的。
  • Foo.bar和Superfoo.bar具有完全相同的签名,访问权限等等。
  • Superfoo.bar 可能分配不同,但这是一个实现细节

这让我想起了20年前的宗教战争,不pipe是C ++还是Java,都是“真正”面向对象的,因为毕竟都暴露了不是“真正的”对象的基本types – 所以,例如,你不能从intinheritance但可以从Integer