为什么单例对象更面向对象?
在 Scala 编程:综合分步指南中,作者说道:
Scala 更出色的一种方式 与Java相比,面向对象的一点是 Scala 中的类不能有静态 成员。相反,Scala 有单例 对象。
为什么 singleton 对象更面向对象?不使用静态成员而是使用单例对象有什么好处?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
尝试“大局观”;其中大部分已在其他答案中涵盖,但似乎没有一个全面的答复将所有内容放在一起并连接起来。所以这里...
类上的静态方法不是对象上的方法,这意味着:
类的静态成员不能作为参数传递给某个函数
(并且由于上述几点...)
的全部要点是它们可以从父对象继承,实现接口,并作为参数传递 - 静态成员具有没有这些属性,因此它们不是真正面向对象的,它们只不过是一个命名空间。
另一方面,单例对象是对象社区的成熟成员。
单例的另一个非常有用的属性是,它们可以在以后的某个时间点轻松更改为不是单例,如果从静态方法开始,这是一个特别痛苦的重构。
想象一下,您设计了一个用于打印地址的程序,并通过某个类上的静态方法表示与打印机的交互,然后您希望能够添加第二台打印机并允许用户选择他们将使用哪一台......这不是一次有趣的经历!
Trying for the "big picture"; most of this has been covered in other answers, but there doesn't seem to be a single comprehensive reply that puts it all together and joins the dots. So here goes...
Static methods on a class are not methods on an object, this means that:
The static members of a class can't be passed as an argument to some function
(and because of the above points...)
The whole point of objects is that they can inherit from parent objects, implement interfaces, and be passed as arguments - static members have none of these properties, so they aren't truly object-oriented, they're little more than a namespace.
Singleton objects, on the other hand, are fully-fledged members of the object community.
Another very useful property of singletons is that they can easily be changed at some later point in time to not be singletons, this is a particularly painful refactoring if you start from static methods.
Imagine you designed a program for printing addresses and represented interactions with the printer via static methods on some class, then later you want to be able to add a second printer and allow the user to chose which one they'll use... It wouldn't be a fun experience!
单例对象的行为类似于类,因为它们可以扩展/实现其他类型。
在 Java 中仅使用静态类无法做到这一点——它比 Java 单例模式,带有
getInstance
,它允许(至少)更好的命名空间/稳定标识符并隐藏区别。Singleton objects behave like classes in that they can extend/implement other types.
Can't do that in Java with just static classes -- it's pretty sugar over the Java singleton pattern with a
getInstance
that allows (at least) nicer namespaces/stable identifiers and hides the distinction.提示:这称为面向对象编程。
严重地。
也许我错过了一些根本上重要的东西,但我不明白有什么大惊小怪的:对象比非对象更面向对象,因为它们是对象。这真的需要解释吗?
注意:虽然听起来确实是这样,但我真的不想在这里显得沾沾自喜。我查看了所有其他答案,发现它们非常令人困惑。对我来说,很明显,根据“面向对象”的定义,对象和方法比命名空间和过程(这就是静态“方法”的真正含义)更加面向对象。
使用单例对象的另一种方法是使类本身成为对象,例如 Ruby、Python、Smalltalk、Newspeak 就是这样做的。
Hint: it's called object-oriented programming.
Seriously.
Maybe I am missing something fundamentally important, but I don't see what the fuss is all about: objects are more object-oriented than non-objects because they are objects. Does that really need an explanation?
Note: Although it sure sounds that way, I am really not trying to sound smug here. I have looked at all the other answers and I found them terribly confusing. To me, it's kind of obvious that objects and methods are more object-oriented than namespaces and procedures (which is what static "methods" really are) by the very definition of "object-oriented".
An alternative to having singleton objects would be to make classes themselves objects, as e.g. Ruby, Python, Smalltalk, Newspeak do.
对于静态成员,没有对象。该类实际上只是一个名称空间。
在单例中,总是至少有一个对象。
老实说,这是令人毛骨悚然的。
For static members, there is no object. The class really just is a namespace.
In a singleton, there is always at least one object.
In all honesty, it's splitting hairs.
它更加面向对象,因为对于给定的 Scala 类,每个方法调用都是对该对象的方法调用。在 Java 中,静态方法不与对象状态交互。
事实上,给定类
A
的对象a
以及静态方法m()
,调用am 被认为是不好的做法()
。相反,建议调用Am()
(我相信 Eclipse 会给你一个警告)。 Java 静态方法不能被覆盖,它们只能被另一个方法隐藏:am()
会打印什么?在 Scala 中,您可以将静态方法粘贴到伴生对象 A 和 B 中,并且意图会更清晰,因为您将显式引用伴生 A 或 B。
在 Scala 中添加相同的示例:
It's more object oriented in the sense that given a Scala class, every method call is a method call on that object. In Java, the static methods don't interact with the object state.
In fact, given an object
a
of a classA
with the static methodm()
, it's considered bad practice to calla.m()
. Instead it's recommended to callA.m()
(I believe Eclipse will give you a warning). Java static methods can't be overridden, they can just be hidden by another method:What will
a.m()
print?In Scala, you would stick the static methods in companion objects A and B and the intent would be clearer as you would refer explicitly to the companion A or B.
Adding the same example in Scala:
在某些情况下,存在一些可能很重要的差异。在Java中你
无法覆盖静态方法所以如果你有类静态方法您将无法自定义和覆盖其部分行为。如果您使用单例对象,您可以只插入从子类创建的单例。
There is some difference that may be important in some scenarios. In Java you
can't override static method so if you had class with static methods you would not be able to customize and override part of its behavior. If you used singleton object, you could just plug singleton created from subclass.
这确实是一个营销问题。考虑两个例子:
现在,这里有哪些可观察到的差异?
它让我想起了 20 年前关于 C++ 或 Java 是否“真正”面向对象的宗教战争,因为毕竟两者都暴露了原始类型不是“真正的”对象——因此,例如您不能从
int
继承,但可以从Integer
继承。It's a marketing thing, really. Consider two examples:
Now, what are the observable differences here?
It reminds me of the religious wars 20 years ago over whether C++ or Java were "really" Object Oriented, since after all both exposed primitive types that aren't "really" objects -- so, for example you can't inherit from
int
but can fromInteger
.