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

发布于 2024-09-30 17:18:14 字数 361 浏览 2 评论 0 原文

Scala 编程:综合分步指南中,作者说道:

Scala 更出色的一种方式 与Java相比,面向对象的一点是 Scala 中的类不能有静态 成员。相反,Scala 有单例 对象。

为什么 singleton 对象更面向对象?不使用静态成员而是使用单例对象有什么好处?

In Programming in Scala: A Comprehensive Step-by-Step Guide, the author said:

One way in which Scala is more
object-oriented than Java is that
classes in Scala cannot have static
members. Instead, Scala has singleton
objects.

Why is a singleton object more object-oriented? What's the good of not using static members, but singleton objects?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

很快妥协 2024-10-07 17:18:14

尝试“大局观”;其中大部分已在其他答案中涵盖,但似乎没有一个全面的答复将所有内容放在一起并连接起来。所以这里...

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

  1. 静态成员不能从父类/特征继承
  2. 静态成员不能用于实现接口
  3. 类的静态成员不能作为参数传递给某个函数

    (并且由于上述几点...)

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

的全部要点是它们可以从父对象继承,实现接口,并作为参数传递 - 静态成员具有没有这些属性,因此它们不是真正面向对象的,它们只不过是一个命名空间。

另一方面,单例对象是对象社区的成熟成员。


单例的另一个非常有用的属性是,它们可以在以后的某个时间点轻松更改为不是单例,如果从静态方法开始,这是一个特别痛苦的重构。

想象一下,您设计了一个用于打印地址的程序,并通过某个类上的静态方法表示与打印机的交互,然后您希望能够添加第二台打印机并允许用户选择他们将使用哪一台......这不是一次有趣的经历!

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:

  1. Static members can't be inherited from a parent class/trait
  2. Static members can't be used to implement an interface
  3. The static members of a class can't be passed as an argument to some function

    (and because of the above points...)

  4. Static members can't be overridden
  5. Static members can't be polymorphic

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!

云淡风轻 2024-10-07 17:18:14

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

在 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.

§对你不离不弃 2024-10-07 17:18:14

提示:这称为面向对象编程。

严重地。

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

注意:虽然听起来确实是这样,但我真的不想在这里显得沾沾自喜。我查看了所有其他答案,发现它们非常令人困惑。对我来说,很明显,根据“面向对象”的定义,对象和方法比命名空间和过程(这就是静态“方法”的真正含义)更加面向对象。

使用单例对象的另一种方法是使类本身成为对象,例如 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.

萌酱 2024-10-07 17:18:14

对于静态成员,没有对象。该类实际上只是一个名称空间。

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

老实说,这是令人毛骨悚然的。

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.

赴月观长安 2024-10-07 17:18:14

它更加面向对象,因为对于给定的 Scala 类,每个方法调用都是对该对象的方法调用。在 Java 中,静态方法不与对象状态交互。

事实上,给定类 A 的对象 a 以及静态方法 m(),调用 am 被认为是不好的做法()。相反,建议调用 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();
        a.m();
    }
}

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
    A.m() // cannot call a.m()
  }
}

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 class A with the static method m(), it's considered bad practice to call a.m(). Instead it's recommended to call A.m() (I believe Eclipse will give you a warning). Java static methods can't be overridden, they can just be hidden by another method:

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();
        a.m();
    }
}

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:

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
    A.m() // cannot call a.m()
  }
}
翻了热茶 2024-10-07 17:18:14

在某些情况下,存在一些可能很重要的差异。在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.

小女人ら 2024-10-07 17:18:14

这确实是一个营销问题。考虑两个例子:

class foo
   static const int bar = 42;
end class

class superfoo
    Integer bar = ConstInteger.new(42);
end class

现在,这里有哪些可观察到的差异?

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

它让我想起了 20 年前关于 C++ 或 Java 是否“真正”面向对象的宗教战争,因为毕竟两者都暴露了原始类型不是“真正的”对象——因此,例如您不能从 int 继承,但可以从 Integer 继承。

It's a marketing thing, really. Consider two examples:

class foo
   static const int bar = 42;
end class

class superfoo
    Integer bar = ConstInteger.new(42);
end class

Now, what are the observable differences here?

  • in a well-behaved language, the additional storage created is the same.
  • Foo.bar and Superfoo.bar have exactly the same signatures, access, and so on.
  • Superfoo.bar may be allocated differently but that's an implementation detail

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 from Integer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文