有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么拥有静态成员会使语言不那么面向对象?

我现在正在学习Scala,在Odersky的Scala编程第二版中,我遇到了这样一种说法:

one way in which Scala is more object-orientated than Java is that classes in Scala cannot have static members.

我对Java或Scala都没有足够的经验来理解这种比较。为什么有静态成员会使语言不那么面向对象


共 (6) 个答案

  1. # 1 楼答案

    静态成员属于类而不是对象,而oop的主要概念在于类的各个对象之间的关系

  2. # 2 楼答案

    好吧,对于静态成员,比如方法,你没有任何要创建的对象,但是你可以调用这样的静态方法。您只需要静态类名就可以为这些方法设置名称空间,例如:

    long timeNow = System.currentTimeMillis(); // no object creation
    

    这给人一种过程语言的感觉

  3. # 3 楼答案

    对于确切地说对象定向的含义,有几种相互矛盾的定义。然而,有一件事他们都可以达成一致:动态调度是OO定义的一个基本部分

    静态方法是静态的(duh),而不是动态的,因此根据定义,它们不是面向对象的

    从逻辑上讲,一种具有非面向对象特性的语言在某种意义上比一种没有这种特性的语言“更少面向对象”

  4. # 4 楼答案

    Java中的static方法是对类本身进行操作的方法,不需要先创建对象。例如,这一行:

    int c = Integer.parseInt("5");
    

    Integer.parseInt()是静态的,因为我在使用它之前不必去Integer i = new Integer();;这不是对我创建的任何特定对象进行操作,因为它总是一样的,更像是一个典型的过程函数调用,而不是面向对象的方法。如果我必须为每个调用创建一个对象,并以这种方式封装所有内容,而不是允许static将方法用作假过程函数,那么它更面向对象

  5. # 5 楼答案

    奥德斯基的说法是正确和有意义的,但有些人不明白他的意思

    假设在Java中有一个带有方法f的类Foo:

    class Foo {
      int f() { /* does something great */ }
    }
    

    您可以编写一个接受Foo并对其调用f的方法:

    void g(Foo foo) { foo.f(); }
    

    也许有一个类subfo扩展了Foo;g也在这方面工作。可以有一整套通过继承或接口关联的类,它们都可以与g一起使用

    现在让我们把f方法变成静态的:

    class Foo {
      static int f() { /* does something great */ }
    }
    

    我们能把这个新的Foo和g一起使用吗

    g(Foo);  // No, this is nonsense.
    

    该死。好的,让我们更改g的签名,这样我们就可以将Foo传递给它,并让它调用f

    oops——我们不能。我们不能传递对Foo的引用,因为Foo不是某个类的实例。这里的一些评论人士感到困惑的是,有一个类对象对应于Foo,但正如Sotirios试图解释的那样,该类对象没有f方法,Foo也不是该类的实例。Foo不是任何事物的实例;它根本不是一个物体。Foo的Class对象是Class类的一个实例,该类包含有关Foo的信息(可以将其视为Foo的内部Wikipedia页面),并且与讨论完全无关。维基百科的“老虎”页面不是老虎

    在Java中,“原语”如3和“x”不是对象。它们是Scala中的对象。为了提高性能,您的程序将在执行期间尽可能使用JVM原语3和“x”,但在您编写代码的级别上,它们实际上是对象。在Java中,它们是而不是对象,这一事实对任何试图编写处理所有数据类型的代码的人来说都是非常不幸的后果——你必须有特殊的逻辑和额外的方法来覆盖原语。如果你看过或写过这样的代码,你就会知道这很糟糕。奥德斯基的声明不是“纯粹主义”;远非如此

    在Scala中,没有任何运行时数据不是对象,也没有任何东西可以调用非对象的方法。在Java中,这些语句都不是真的;Java是一种部分面向对象的语言。在Java中,有些东西不是对象,有些方法不是对象

    Scala的新手通常认为object Foo是Java静态的奇怪替代品,但这是您需要尽快克服的问题。相反,可以将Java的静态方法看作是一个非面向对象的缺点,将Scala的object Foo { ... }看作是以下几点:

    class SomeHiddenClass { ... }
    val Foo = new SomeHiddenClass  // the only instance of it
    

    这里Foo是一个,而不是类型,它实际上是一个对象。它可以传递给一个方法。它可以扩展其他类。例如:

    abstract class AbFoo { def f:Int }
    object Foo extends AbFoo { def f = 2 }
    

    现在,你终于可以说

    g(Foo)
    

    的确,类的“伴生对象”是放置类的非实例方法和数据的好地方。但这个伴生对象是一个对象,所以通常的规则和功能适用

    在Java中,将这些方法放在非对象上——限制它们的使用方式——是一种负担,而不是特性。这肯定是而不是OO

  6. # 6 楼答案

    我不确定我是否完全相信这个论点,但这里有一个可能的理由

    对于一个面向对象的纯粹主义者来说,一切都应该是一个对象,所有状态都应该由对象封装。一个类的任何static成员根据定义都是存在于对象之外的状态,因为您可以使用它并操作它,而无需实例化对象。因此,缺少静态类成员就形成了一种更纯粹的面向对象语言