web-dev-qa-db-ja.com

なぜ、いつクラスを「静的」にする必要がありますか?クラスの「静的」キーワードの目的は何ですか?

多くの言語でのメンバーのstaticキーワードは、そのメンバーにアクセスできるようにするために、そのクラスのインスタンスを作成してはならないことを意味します。ただし、クラス全体をstaticにする理由はありません。なぜ、いつstaticクラスを作成する必要がありますか?

クラスstaticを作成するとどのようなメリットがありますか?つまり、静的クラスを宣言した後でも、インスタンス化せずにアクセスしたいすべてのメンバーを静的として宣言する必要があります。

つまり、たとえば、Mathクラスは、開発者のコ​​ードに影響を与えることなく、通常(静的ではなく)宣言できます。言い換えると、クラスを静的または通常にすることは、開発者には透過的です。

48
Saeed Neamati

クラスがどのように使用されるかをユーザーに明らかにします。たとえば、次のコードを書くのはまったくナンセンスです。

Math m = new Math();

C#はこれを禁止しませんする必要がありますこれを禁止しますが、目的を果たさないため、ユーザーにそのことを伝えることもできます。特定の人々(私を含む)は、プログラミング言語(およびAPI…)をできるだけ制限して、誤用しにくくするという哲学に固執します。許可される操作は、意味があり、(できれば)正しいものだけです。

34
Konrad Rudolph

StackOverflowはこのトピックについて素晴らしい議論を行っています 。参照しやすいように、著者に代わってここにコピーして貼り付けます Mark S. Rasmussen

静的クラスについての考えを 以前のスレッド に書いた。

静的メソッドで満たされたユーティリティクラスが大好きでした。彼らは、さもなければ冗長性とメンテナンスの地獄を引き起こすことの周りにあるヘルパーメソッドの素晴らしい統合を作りました。それらは非常に使いやすく、インスタンス化も廃棄もありません。ただ火を忘れないでください。これは、サービス指向アーキテクチャーを作成するための私の最初の無意識の試みだったと思います-仕事をして他には何もない多くのステートレスなサービス。しかし、システムが成長するにつれて、ドラゴンがやってきます。

多型

幸いにもうなり声を上げるメソッドUtilityClass.SomeMethodがあるとします。突然、機能を少し変更する必要があります。ほとんどの機能は同じですが、それでもいくつかの部分を変更する必要があります。静的メソッドでなければ、派生クラスを作成し、必要に応じてメソッドの内容を変更できます。静的メソッドなので、できません。確かに、古いメソッドの前後に機能を追加する必要がある場合は、新しいクラスを作成して、その中にある古いクラスを呼び出すことができますが、それは非常に重要です。

インターフェースの問題

論理的な理由により、静的メソッドはインターフェースを介して定義できません。また、静的メソッドをオーバーライドすることはできないため、静的クラスは、それらをインターフェースで渡す必要がある場合には役に立ちません。これにより、戦略パターンの一部として静的クラスを使用できなくなります。インターフェースの代わりにデリゲートを渡すことにより、いくつかの問題にパッチを当てるかもしれません。

テスト

これは基本的に、上記のインターフェースの問題と関連しています。実装を交換する能力は非常に限られているため、製品コードをテストコードに置き換えるのも困難です。繰り返しになりますが、それらをラップすることはできますが、実際のオブジェクトの代わりにラッパーを受け入れることができるようにするために、コードの大部分を変更する必要があります。

ブロブを育成します

通常、静的メソッドはユーティリティメソッドとして使用され、ユーティリティメソッドは通常異なる目的を持つため、一貫性のない機能で満たされた大きなクラスがすぐに完成します。理想的には、各クラスはシステム内で単一の目的を持つ必要があります。目的が明確に定義されている限り、クラスは5倍にしたほうがいいです。

パラメータクリープ

まず、そのかわいくて無邪気な静的メソッドは、単一のパラメーターを取るかもしれません。機能が成長するにつれて、いくつかの新しいパラメーターが追加されます。間もなく、オプションのパラメーターがさらに追加されるため、メソッドのオーバーロードを作成します(または、パラメーターをサポートする言語でデフォルト値を追加します)。やがて、10個のパラメーターを受け取るメソッドがあります。最初の3つだけが本当に必要であり、パラメーター4から7はオプションです。しかし、パラメーター6が指定されている場合、7〜9も入力する必要があります...この静的メソッドが行ったことを行うという単一の目的でクラスを作成した場合、必要なパラメーターをコンストラクター、およびユーザーがプロパティを介してオプションの値を設定できるようにする、またはメソッドが同時に複数の相互依存値を設定することを可能にする。また、メソッドがこの程度の複雑さまで成長した場合は、とにかく独自のクラスに属している必要があります。

理由もなくクラスのインスタンスを作成するよう要求するコンシューマ

最も一般的な議論の1つは、クラスのコンシューマーがこの単一のメソッドを呼び出すためのインスタンスを作成し、その後インスタンスを使用しないことを要求することです。クラスのインスタンスの作成は、ほとんどの言語で非常に安価な操作であるため、速度は問題になりません。消費者に追加のコード行を追加することは、将来的にはるかに保守可能なソリューションの基盤を構築するための低コストです。そして最後に、インスタンスの作成を避けたい場合は、簡単に再利用できるようにするクラスのシングルトンラッパーを作成するだけです。ただし、これにより、クラスがステートレスである必要があります。ステートレスではない場合でも、すべてを処理する静的なラッパーメソッドを作成する一方で、長期的にはすべての利点を利用できます。最後に、インスタンス化をシングルトンのように隠すクラスを作成することもできます。MyWrapper.Instanceは、新しいMyClass()を返すだけのプロパティです。

シスだけが絶対的に扱います

もちろん、静的メソッドの嫌いには例外があります。膨張のリスクをもたらさない真のユーティリティクラスは、静的メソッド(System.Convertなど)の優れたケースです。プロジェクトが将来のメンテナンスの必要がない1回限りのものである場合、全体的なアーキテクチャはそれほど重要ではありません-静的か非静的かは重要ではありません-開発速度は重要です。

標準、標準、標準!

インスタンスメソッドを使用しても、静的メソッドの使用が妨げられることはなく、その逆も同様です。差別化の背後に理由があり、それが標準化されている限り。さまざまな実装方法で広がっているビジネスレイヤーを見ることほど悪いことはありません。

25
Rick

staticクラスが 拡張メソッド を許可し、既存のタイプを安全に拡張する(メソッド定義をインターフェースに追加するを含む)ことを他の誰も言及していないことに驚きます所有しないでください。たとえば、Scala

trait MyFoo {
  def foo: Int
  def plusFoo(a: Int) = foo + a
}

c#では次のように表現できます

public interface IMyFoo {
  int Foo();
}

public static class MyFooExtensions {
  public static int PlusFoo(this IMyFoo f, int a) {
    return f.Foo() + a;
  }
}
16
Frank Shearar

私にとって、静的クラス(C#の場合)は、関数を呼び出すようなものです。

例えば

public static string DoSomething(string DoSomethingWithThisString){}

文字列を渡して文字列を返します。すべてがそのメソッドに含まれています。メンバー変数などへのアクセスなし.

正直なところ、私にとっての主な用途は、コード行を減らすことです。

なぜか:

MyClass class = new MyClass();
String s = class.DoSomething("test");

これができるとき:

String s = MyClass.DoSomething("test");

そのため、クラスを必要とせずに何かをしたいので、タイピングを少なくする必要がある場合は、静的クラスを使用します。

Mark S.ポイントは有効ですが、私にとっていくつかのユーティリティメソッドがある場合、それらを1つのライナーとして参照する関数を呼び出すよりも簡単です。

それは単純なことかもしれませんが、ほとんどの場合、私はstaticを使用しています。

3
Jon Raynor