web-dev-qa-db-ja.com

なぜScalaはクラス内に静的メンバーを持たないのですか?

私はあなたができることを知っています 間接的に定義する 類似した何かを達成するコンパニオンオブジェクトを使用しますが、言語設計がクラス定義から抜け落ちた静的である理由を疑問に思います。

50
numan salati

この質問は、scala users google groupとBill Vennersの "scalaでのプログラミング"の著者の1人にも返事がありました。

これを見てください: https://groups.google.com/d/msg/scala-user/5jZZrJADbsc/6vZJgi42TIMJ および https://groups.google.com/d/msg/scala-user/5jZZrJADbsc/oTrLFtwGjpEJ

抜粋は次のとおりです。

1つの目標は、すべての値をオブジェクト、すべての操作をメソッド呼び出しにすることにより、単純にすることでした。 Javaの静的およびプリミティブは特殊なケースであり、ある意味で言語をより「複雑」にします。

しかし、私が思う別の大きなものは、Javaの静的をin Scalaにマッピングできるものがあることです(なぜなら、Scalaは相互運用のためにJavaの静的にマッピングする構成が必要だったためしかし、その恩恵はOO継承/ポリモーフィズムです。シングルトンオブジェクトは実際のオブジェクトです。スーパークラスを拡張したり、特性を混在させたり、そのまま渡したりすることができます。 。それは実際には非常に便利であることがわかりました。

また、Martin Oderskyとのこのインタビューをご覧ください(Scalaセクション)のオブジェクト指向イノベーションにスクロールダウンしてください http://www.artima.com/scalazine/articles/goals_of_scala .html

抜粋は次のとおりです。

まず、すべての値がオブジェクトであり、すべての操作がメソッド呼び出しであり、すべての変数が何らかのオブジェクトのメンバーである、純粋なオブジェクト指向言語になりたかった。そのため、静的要素は必要ありませんでしたが、それらを置き換えるものが必要だったため、シングルトンオブジェクトの構造を作成しました。しかし、シングルトンオブジェクトでさえ、依然としてグローバル構造です。そのため、グローバル構造ができたらそれ以上変更できないため、それらをできるだけ使用しないことが課題でした。インスタンス化することはできません。テストするのは非常に難しいです。何らかの方法で変更することは非常に困難です。

要約するには:

関数型プログラミングの観点からは、静的メンバーは一般に悪いと見なされます(これを参照してください post Gilad Bracha-Java genericsの父。これは主に副作用と関係しています。しかし、scala=は、Java(したがって、静的をサポートする必要がありました)と相互運用可能であり、完全にではありませんが)回避)静的状態のために作成されるグローバル状態、scala=をそれらをコンパニオンオブジェクトに分離することにしました。

コンパニオンオブジェクトには、拡張可能という利点もあります。継承とミックスイン構成を活用します(相互運用のために静的機能をエミュレートすることとは別に)。

16
numan salati

OのOOは、クラスではなく、「オブジェクト」を表します。オブジェクト指向であることは、オブジェクトまたはインスタンス(必要に応じて)に関するものです。

スタティックはオブジェクトに属しません。継承することはできません。ポリモーフィズムには参加しません。簡単に言えば、静的はオブジェクト指向ではありません。

一方、Scalaはisオブジェクト指向です。その言語から開発者を引き付けるために、C++のように振る舞うために特に一生懸命に努力したJavaよりもはるかに。

これらは、C++によって考案されたハックであり、手続き型プログラミングとOOプログラミングの世界を橋渡ししようとしており、Cとの下位互換性が必要でした。同様の理由でプリミティブも認めました。

Scalaは静的関数とプリミティブをドロップします。これは、プロシージャル開発者をなだめる必要があった時代の遺物だからです。これらのことは、オブジェクト指向としてそれ自体を説明したい、適切に設計された言語にはありません。


whyに関しては、本当にオブジェクト指向であることが重要です。メーリングリストでBill Vennersからこのスニペットを恥知らずにコピーして貼り付けます。

しかし、私が見る方法では、シングルトンオブジェクトを使用すると、必要な場所で静的な処理を非常に簡潔に行うことができますが、必要に応じて継承を行うこともできます。 1つの例は、プログラムの静的な部分をテストする方が簡単だということです。これらの部分をモデル化し、どこでもその特性を使用する特性を作成できるからです。次に、本番プログラムではこれらの特性のシングルトンオブジェクト実装を使用しますが、テストではモックインスタンスを使用します。

自分でもっと良くできなかったでしょう!

したがって、何かの1つだけを作成したい場合は、静的とシングルトンの両方が仕事をすることができます。しかし、その1つのことをどこかから動作を継承させたい場合、静的関数は役に立ちません。

私の経験では、特にScalaをしばらく使用した後は、当初考えていたよりもはるかに多くその能力を使用する傾向があります。

56
Kevin Wright

これらは、静力学が物事を複雑にする可能性があることを考えるときに頭に浮かぶものです:

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アノテーションは、もちろんオプションであり、友好的です"静的メソッドf()タイプAから静的メソッドにアクセスする必要があります"警告。これ私たちを導く

2)ものにアクセスする「静的な方法」は、物事を複雑にするさらに特別なルールです。

静的メンバーは抽象的であってはなりません。すべてを手に入れることはできませんね。

繰り返しになりますが、これらはほんの数分間考えた後に思いついたものです。私は他の多くの理由があるに違いない、なぜ静的がOOパラダイムに適合しないのか。

4
agilesteel

確かに、静的メンバーは存在しませんが、シングルトンオブジェクトを各クラスに関連付けることは可能です。

class MyClass {
}

object MyClass {
}

同様の結果を得るために

2
Simone

オブジェクト指向プログラミングは、すべてオブジェクトとその状態に関するものです(Javaの状態フルおよびステートレスオブジェクトに触れない)。ストレスをかけようとしています「静的はオブジェクトに属していません」。静的フィールドはオブジェクトの状態を表すために使用できませんしたがって、オブジェクトから引き離すことは合理的です。

1
Balaji Reddy