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

时间:2010-11-06 05:36:22

标签: scala

Programming in Scala: A Comprehensive Step-by-Step Guide中,作者说:

  

Scala更多的一种方式   面向对象比Java更强   Scala中的类不能有静态   成员。相反,Scala有单身人士   对象。

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

7 个答案:

答案 0 :(得分:58)

尝试“大局”;大部分内容已经在其他答案中得到了解释,但似乎没有一个全面的回复将所有内容放在一起并加入点。所以这里......

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

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

    (由于以上几点......)

  4. 无法覆盖静态成员
  5. 静态成员不能是多态的
  6. 对象的重点是它们可以从父对象继承,实现接口,并作为参数传递 - 静态成员没有这些属性,因此它们不是真正面向对象的,它们只是命名空间。

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


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

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

答案 1 :(得分:12)

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

不能仅使用静态类在Java中执行此操作 - 它在Java singleton pattern上的相当于,其中getInstance允许(至少)更好的命名空间/稳定标识符和隐藏区别。

答案 2 :(得分:10)

提示:它被称为 object - 面向编程。

严重。

也许我遗漏了一些根本重要的东西,但我看不出大惊小怪:对象比非对象更面向对象,因为它们是对象。这真的需要解释吗?

注意:虽然听起来确实如此,但我真的试图在这里沾沾自喜。我查看了所有其他答案,我发现它们非常令人困惑。对我来说,显而易见的是,对象和方法比名称空间和过程更加面向对象(这是静态“方法”实际上是什么),这是“面向对象”的定义。 / p>

具有单例对象的替代方案是使类本身成为对象,例如, Ruby,Python,Smalltalk,Newspeak。

答案 3 :(得分:2)

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

在单身人士中,总是至少有一个对象。

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

答案 4 :(得分:2)

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

事实上,如果使用静态方法a给出A类的对象m(),则调用a.m()被认为是不好的做法。相反,建议调用A.m()(我相信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();
    }
}

a.m()会打印什么?

在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()
  }
}

答案 5 :(得分:2)

在某些情况下,某些差异可能很重要。在Java中你 can't override static method所以,如果你有静态方法的类,你将无法自定义和覆盖其部分行为。如果您使用单例对象,则只需插入从子类创建的单例。

答案 6 :(得分:-7)

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

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