web-dev-qa-db-ja.com

どのような状況で静的メソッドが良い習慣ですか?

私は次の議論を読みました:

プライベートヘルパーメソッドが静的である可能性がある場合は静的である必要があります 、および
クラスにメンバー変数がない場合、すべてのメソッドは静的である必要があります

一般に、静的メソッドを受け入れる人がいるようですが、次の2つの理由から、少し懐疑的です。

  1. それらはテストするのが難しいです。
  2. それらはOOの原則に違反します。(これらは関数であり、メソッドではない、と人は言いました。)

そして、最も受け入れられる静的メソッドはprivate staticメソッドです。しかし、なぜ静的メソッドが存在するのでしょうか。また、どのような状況で静的メソッドを採用することが最優先されるのでしょうか。

37
Winston Chen

静的メソッドは、それ自体でテストするのは難しくありません。問題は、静的メソッドを置き換えることができないため、静的メソッドを呼び出す他のコードをテストするのが難しいことです。

静的メソッドは、プライベートの場合、または「ユーティリティ」メソッドの場合のいずれかで問題ないと思います。文字列のエスケープを実行します。問題は、テスト内でモックアウトまたはその他の方法で置き換えることができるようにしたいものに静的メソッドを使用するときに発生します。ファクトリメソッドも役立ちますが、依存性注入は一般的に優れたアプローチです-繰り返しますが、機能を置き換えることができるかどうかに部分的に依存しますテストで。

「OO」ではないことに関しては、一般的にOO言語で書くすべてが「純粋な」OOである必要はありません。OO以外のルートは単により実用的であり、より単純なコードにつながることがあります。 Eric Lippertがこれについて素晴らしいブログ投稿をしていますが、残念ながら今は見つかりません。ただし、 この投稿 に関連するコメントがあります。静的メソッドではなく拡張メソッドについて説明していますが、原理は同じです。

拡張メソッドは「OOP十分ではない」と批判されることがよくあります。これはカートを馬の前に置いているようです。OOP生産性を高めるために互いの作業の内部詳細を知る必要のない人々のチームによって作成された大規模なソフトウェアプロジェクトの構造化のガイドラインを提供することです。C#の目的は、お客様が利用できる便利なプログラミング言語になることです。明らかにOOPは便利で人気があるので、OOPスタイルで簡単にプログラミングできるようにしています。 C#。ただし、C#の目的は「OOP言語」になること」ではありません。機能は、抽象的な学術に厳密に準拠しているかどうかではなく、お客様にとって有用かどうかに基づいて評価されます。言語をオブジェクト指向にするものの理想。一貫性のある有用なものを作成できる限り、oo、function、procedural、inperative、declarativeなどからアイデアを喜んで取り入れます。お客様に利益をもたらす製品。

64
Jon Skeet

静的メソッドは、functionsの場合、つまり、IOを実行せず、内部状態を持たず、パラメーターのみを使用して戻り値を計算する場合は、間違いなく問題ないと思います。

これをパラメーターの状態を変更するメソッドにも拡張しますが、これが過度に行われる場合、静的メソッドは、主に操作されるパラメータークラスのインスタンスメソッドである必要があります。

20

これについて少し考えてみてください。 OOコーディングでは、すべての関数呼び出しは実際には次のようになります。

method(object this, object arg1, object arg2)ここで、これは呼び出しているオブジェクトです。実際には、このためのシンタックスシュガーだけです。さらに、オブジェクト変数などがあるため、変数のスコープを明確に定義できます。

静的メソッドには、単に「this」パラメーターがありません。つまり、変数を渡して、結果を返す可能性があります。 1.)人々がそれらを避ける主な理由は、静的メソッドへのインターフェースを(まだ)作成できないため、静的メソッドをモックアウトしてテストすることはできません。

次に、OOはプロシージャ関数などです。静的メソッドは特定の状況では非常に意味がありますが、オブジェクトのメソッドにすることはいつでも可能です。

念のために言っておきますが、ハックなしではこれを削除することはできません。

static void Main(string[] args)
{
}

アプリケーションを開始するコードは、オブジェクトへの参照なしで呼び出すことができる必要があります。したがって、シナリオでそれらを使用することを選択するかどうかは、要件に基づいて決定されるため、柔軟性が得られます。

6
Spence

静的メソッドは、シングルトンパターンの柔軟性が高すぎるほとんどの状況で問題ありません。

たとえば、プリミティブを累乗するなどの単純なユーティリティを考えてみましょう。明らかに、その中にポリモーフィズムを含める必要はありません。プリミティブ値は静的タイプであり、数学演算は明確に定義されており、変更されません。 2つあるという状況になるとは限りません 異なる実装 すべてのクライアントコードを書き直さずにそれらを切り替える方法はありません。


(皮肉なオフ)

最近のJVMは、インターフェースの実装が1つだけロードされている場合、小さな呼び出しをインライン化するのに非常に優れています。コードのプロファイルを作成し、ユーティリティをインターフェイスにディスパッチすることがオーバーヘッドであることがわかっていない限り、 ユーティリティメソッドをインターフェイスに (必要に応じて変更できます)を作成しない理由はありません。

4
Pete Kirkham

静的メソッドの明確なケースはクラスを変更できないために動的にできない場合だと思います。

これはJDKオブジェクト、および外部ライブラリからのすべてのオブジェクト、およびプリミティブ型に一般的です。

2
KLE

私はしばしば、パブリックコンストラクターの代わりに、またはパブリックコンストラクターと組み合わせて静的ファクトリメソッドを使用します。

私はこれを行います。コンストラクターが実行するとは思わないことを実行するコンストラクターが必要な場合です。つまりファイルまたはデータベースから設定をロードします。

このアプローチは、それらが何をするかに基づいて、「コンストラクター」に名前を付ける可能性も提供します。これは、パラメーター自体がコンストラクターで何が起こるかを理解するのに十分でない場合に特に役立ちます。

Sunはこのアプローチを

Class.forName("Java.lang.Integer");

そして

Boolean.valueOf("true");
2
Fedearne

静的メソッドのもう1つの良いシナリオは、 ファクトリパターン の実装です。ここでは、クラスのインスタンスを特定の方法で構築できます。

Calendar クラスを考えてみましょう。このクラスには、静的なgetInstanceメソッドのセットがあり、それぞれが目的のTimeZoneおよび/またはLocaleまたはデフォルト。

2
akf

まず第一に、静的メソッドを却下することはできません-人々がまだそれを使用している理由があります。

  1. 一部のデザインパターンは静的メソッドに基づいています。たとえば、シングルトンです。

    Config.GetInstance();

  2. ヘルパー関数。バイトストリームがあり、それを16進数の文字列に変換する関数が必要だとします。

静的メソッドには多くの用途がありますが、それは一部の人々がそれを乱用しすぎることを意味しないと言っています(人々がコードを乱用する場合はコードレビューが最良のオプションです)。

1
Danni

Utilクラスは静的でも問題ありません。上記の他の誰かの例のように、文字列をエスケープします。問題は、それらのutilsクラスがモックしたい関数を実行するときにあります。たとえば、Apache CommonsのFileUtilsクラス-実際のファイルを操作せずに、ファイルの相互作用をモックしたい場合がよくあります。これがインスタンスクラスであれば、簡単です。

1
Paul

静的なメソッドをリファクタリングする方がはるかに簡単です。カップリングを緊密にするフィールドメンバーへの不必要な参照を思いとどまらせます。また、相互作用するオブジェクトを明示的に渡すため、呼び出しコードを理解しやすくなります。

1

通常、単一のインスタンスが正常に機能する場合は、静的メソッドを避けます。その単一のインスタンスはインターフェースを実装でき、簡単にモックすることができます。私は決して言っているわけではありませんが、私はめったに静力学を使用しません。スタティックを使用する場合は、チームがクリアする必要があることをチームに伝えます。私の答えはほとんどありません。

0
John Wright