为什么单例对象更面向对象?
在Scala编程:一个全面的分步指南 ,作者说:
Scala比Java更面向对象的一种方式是Scala中的类不能有静态成员。 相反,斯卡拉有单身的对象。
为什么单例对象更面向对象? 什么是不使用静态成员,但单身人士的对象?
试图“大局面”; 其他大部分内容已经被其他答案所覆盖,但似乎并没有一个全面的答复,把所有的答案放在一起,并join了点。 所以这里…
类上的静态方法不是对象的方法,这意味着:
- 静态成员不能从父类/特征inheritance
- 静态成员不能用来实现一个接口
-
一个类的静态成员不能作为parameter passing给某个函数
(因为以上几点…)
- 静态成员不能被覆盖
- 静态成员不能是多态的
对象的要点是它们可以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 – 所以,例如,你不能从int
inheritance但可以从Integer
。