【问题标题】:Why doesn't Scala have static members inside a class?为什么 Scala 在类中没有静态成员?
【发布时间】:2011-11-10 06:14:18
【问题描述】:

我知道你可以间接定义它们 用伴随对象实现类似的东西,但我想知道为什么作为一种语言设计从类定义中删除了静态。

【问题讨论】:

  • 我的猜测是,如果没有static,Scala 的整体设计就会简化。我们已经有了类和作为类实例的对象,所以单例对象(只实例化一次的类)的想法非常自然和简单。顺便说一句,在 JVM 级别,单例对象实际上是一个类的单个实例。单例对象上的方法不会编译为 static 方法。这对于定义继承自特征的单例对象之类的事情很有用。
  • @kipton 不错的想法,而且非常接近目标。最初的决定是放弃静态(因为不是 OO,并且有几个命名空间问题)。然后将单例对象添加到语言中,作为一种更好的方式来填补静态在 Java(和其他 C++ 衍生品)中所扮演的角色。
  • 我编辑了这个问题以澄清 Scala 的单例对象的成员与 Java 的 static 成员并不完全相同。
  • @kipton,实际上,如果您查看生成的字节码,您会看到该对象被编译为具有静态方法的类。
  • @Numan - 所谓的“静态转发器”是专门为支持 Java 互操作而实现的,Scala 内部不使用这些方法。

标签: class scala static language-design static-members


【解决方案1】:

是的,静态成员不存在,但是,可以将一个单例对象关联到每个类:

class MyClass {
}

object MyClass {
}

获得相似的结果

【讨论】:

    【解决方案2】:

    当我想到静态如何使事情复杂化时,这些是我脑海中蹦出来的东西:

    1) 继承和多态都需要特殊的规则。这是一个例子:

    // This is Java
    public class A {
      public static int f() {
        return 10;
      }
    }
    
    public class B extends A {
      public static int f() {
        return 5;
      }
    }
    
    public class Main {
      public static void main(String[] args) {
        A a = new A();
        System.out.println(a.f());
        B b = new B();
        System.out.println(b.f());
        A ba = new B();
        System.out.println(ba.f());
       }
    }
    

    如果您对打印出来的内容有 100% 的把握,那对您有好处。我们其他人可以放心地依赖强大的工具,例如@Override 注解,这当然是可选的并且友好的“类型 A 的静态方法 f() 应该以静态方式访问”警告。这导致我们

    2) 访问内容的“静态方式”是进一步的特殊规则,它使事情复杂化。

    3) 静态成员不能是抽象的。我猜你不可能拥有一切,对吧?

    再一次,这些只是我考虑了几分钟后想到的事情。我敢打赌还有很多其他原因,为什么静态不适合 OO 范式。

    【讨论】:

      【解决方案3】:

      OO 中的 O 代表“对象”,而不是类。面向对象就是对象或实例(如果您愿意的话)

      静态不属于一个对象,它们不能被继承,它们不参与多态性。简单地说,静态不是面向对象的。

      Scala,另一方面,面向对象的。远远超过 Java,它特别努力表现得像 C++,以吸引该语言的开发人员。

      它们是一种 hack,由 C++ 发明,它试图在过程和 OO 编程的世界之间架起一座桥梁,并且需要向后兼容 C。出于类似的原因,它也承认原语。

      Scala 放弃了静态和原语,因为它们是需要安抚前程序开发人员的时代的遗物。这些东西在任何希望将自己描述为面向对象的精心设计的语言中都没有立足之地。


      关于为什么真正的 OO 很重要,我将无耻地复制 Bill Venners 的这个 sn-p 并将其粘贴到邮件列表中:

      不过,我的看法是,单例对象允许您 以非常简洁的方式在需要的地方做静态的事情,但是 在需要时也可以从继承中受益。一个例子是 更容易测试程序的静态部分,因为你可以使 对这些部分进行建模并在任何地方使用这些特征的特征。然后在 生产程序使用那些的单例对象实现 特征,但在测试中使用模拟实例。

      我自己再好不过了!

      所以如果你只想创建一个东西,那么静态和单例都可以完成这项工作。但如果你想让那一件事从某个地方继承行为,那么静态不会帮助你。

      根据我的经验,您使用该功能的次数往往远远超出您最初的预期,尤其是在您使用 Scala 一段时间之后。

      【讨论】:

      • 其实Java中的statics确实是继承的。
      • @Daniel - 值得商榷,继承在 OO 中具有相当特定的含义。我将静态描述为被拉入范围,而不是继承。当讨论静态字段而不是静态方法时,差异变得很明显。继承的东西也可以真正被覆盖,而不仅仅是被遮蔽。
      • 静态方法是继承的,它们只是不是动态调度的。它们在编译时被解析。在 scala 中的对象中定义它们如何帮助您进行继承或多态性 - 您使用 java 的方法陈述的两个主要缺点?
      • @numan 您可以将它们放在一个 trait 中,它类似于并生成一个 Java 接口。这意味着您可以对接口进行编码,将单例作为实现接口的实例提供,等等。
      • @KevinWright 多么疯狂的咆哮。面向对象几乎是 Scala 目标的相反。 Scala 试图成为函数式,而函数式与面向对象有些矛盾。 Scala 允许将两者混合使用。 Java 也允许新旧混合使用。
      【解决方案4】:

      我还在 scala users google group 上发布了这个问题,而“Programming in scala”的作者之一 Bill Venners 回复了一些见解。

      看看这个:https://groups.google.com/d/msg/scala-user/5jZZrJADbsc/6vZJgi42TIMJhttps://groups.google.com/d/msg/scala-user/5jZZrJADbsc/oTrLFtwGjpEJ

      摘录如下:

      我认为一个 目标很简单,让每个值都成为一个对象, 每个操作都是一个方法调用。 Java 的静态和原语是 特殊情况,这使得语言在某些情况下更加“复杂” 感觉。

      但我认为另一个重要的事情是拥有一些可以映射 Java 的东西 Scala 中的静态数据(因为 Scala 需要一些映射的构造 到 Java 的互操作静态),但这得益于 OO 继承/多态。单例对象是真实对象。他们能 扩展一个超类或混合特征并像这样被传递,然而 它们本质上也是“静态的”。事实证明这非常方便 练习。

      还可以看看 Martin Odersky 的采访(向下滚动到 Scala 中的面向对象创新部分)http://www.artima.com/scalazine/articles/goals_of_scala.html

      摘录如下:

      首先,我们希望成为一种纯面向对象的语言,其中每个值都是一个对象,每个操作都是一个方法调用,每个变量都是某个对象的成员。所以我们不需要静态,但我们需要一些东西来替换它们,所以我们创建了单例对象的构造。但即使是单例对象仍然是全局结构。所以挑战是尽可能少地使用它们,因为当你拥有一个全局结构时,你就不能再改变它了。你不能实例化它。很难测试。很难以任何方式对其进行修改。

      总结:

      从函数式编程的角度来看,静态成员通常被认为是不好的(参见 Gilad Bracha 的 post - java 泛型之父。它主要与全局状态的副作用有关)。但是 scala 必须找到一种与 Java 互操作的方法(因此它必须支持静态)并最小化(尽管不是完全避免)由于静态而创建的全局状态,scala 决定将它们隔离到伴随对象中。

      伴随对象还具有可扩展的优点,即。利用继承和 mixin 组合(与模拟互操作的静态功能分开)。

      【讨论】:

        【解决方案5】:

        面向对象的编程都是关于对象及其状态的(不涉及 Java 中的状态完整和无状态对象)。我试图强调“静态不属于对象”。静态字段不能用于表示对象的状态,因此从对象中提取是合理的。

        【讨论】:

          猜你喜欢
          • 2023-03-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-15
          • 2012-01-21
          • 2012-08-15
          • 1970-01-01
          相关资源
          最近更新 更多