14

[編集]

私の最初の質問は、「なぜ静的か非静的かを決定するのですか?どちらも同じことをします...」でした。

残念ながら、私が本当に避けたかったC#固有の質問に編集されました。

だから、私はいくつかの追加をしましょう:

私がインターフェイスと言うとき、私は C# キーワード インターフェイスを意味するのではなく、C++ インターフェイスのようなものを意味します: オブジェクトを操作するための明確に定義された関数のセット。インターフェイスを弱めると言うときは、同じことを行うさまざまな関数 (静的/非静的) があることを意味します。同じことを行うさまざまな機能がある場合、私のインターフェースはもはや明確に定義されていません。

したがって、Bob the Janitor が投稿したように、Validate() 関数を実装できます。

Document.Validate(myDocumentObject);    

だけでなく、

myConcreteDocumentObject.Validate();

私の Copy() の例に戻るには、次のように Copy() を実装できます。

myConcreteDocument.Copy(toPath);

だけでなく、

Document.Copy(myConcreteDocumentObject, toPath)

また

Document.Copy(fromPath, toPath)

私のドキュメントに属するすべてのファイルを含むフォルダーを考えるとき (この場合、私は具体的なインスタンスに依存していませんが、他のものに依存しています:))。

一般的に、静的クラスではなく静的メソッドについて話しているのです (申し訳ありませんが、言及するのを忘れていたら)。

しかし、Anton Gogolev が言ったように、私の Document クラスは良い例ではなく、適切に設計されていないと思うので、Single Responsibility Principle を確認する必要があると思います。

DocumentClass で動作するある種の ManagerClass を実装することもできます。

例えば:

myDocumentManagerObject.Copy(myConcreteDocumentObject, toPath);

また

myDocumentManagerObject.Copy(myConcreteDocumentObject, toPath);

しかし、アプローチ 1 を参照すると、DocumentObject で何かを行う他のオブジェクト (DocumentManager) ではなく、自分自身でタスクを実行するオブジェクトを作成する傾向があります。

(これがOOPについての宗教的な議論の方向に向かわないことを願っています;))

[/編集]


古いバージョン:

最初は、これは「いつ静的メソッドを使用し、いつ使用しないか」などの非常に基本的な質問のように見えますが、これは私が時々直面するものです (そして、本当の問題が何であるかを説明するのは困難です; おそらくそれは単に1) を使用する (しない) 理由、または 2) を使用する (しない) 理由を取得します。

(私は C# 構文を使用していますが、これは C# 制限の問題ではありません)

OOP では、オブジェクトを操作する (とりわけ) 2 つのアプローチがあります。

1) オブジェクトに何かをさせたい場合は、そうするように伝えます。

myConcreteObject.DoSomething();

物と話しているのと同じです。

2) または、静的メソッドのファンの場合:

ObjectClass.JustDoIt();

ある意味で、静的関数は「気分が良くなる」だけだと思います。そのため、私は静的メソッドを頻繁に使用する傾向があります (具体的なインスタンスから独立するために - 独立性は常に良いことです)。

そのため、クラスを設計するときは、アプローチ 1) とアプローチ 2) のどちらを採用するかを決定しなければならないことがよくあります。

データベースに保存する必要があるドキュメントを表す "Document" クラスがあるとします。

文書

  • ファイルシステムからの 1 つまたは複数の画像ファイルで構成されます (これらは単一のドキュメント ページになります)
  • 参考文献のようなものがあります-ユーザーがドキュメントに関する情報を追加できるフィールド-追加のファイルに保存されます
  • Copy()、AddPage()、RemovePage() などの操作が必要です。

今、私はこのクラスを作成するいくつかの方法に直面しています:

//----- 1) non static approach/talking to objects -----
Document newDocument = new Document();

// Copy document to x (another database, for example)
newDocument.Copy(toPath);

私はこれが好きです: ドキュメントに自分自身をデータベース x にコピーするように指示すると、オブジェクトはそれ自体でコピーを行います。良い。

//----- 2) static approach ----------------------------
Document.Copy(myDocumentObject, toPath);

なぜだめですか?また、いいですね、とても便利に感じます...

では、どれを実装しますか?両方?それとも、一種のヘルパー クラスに静的アプローチを適用しますか? または、アプローチ 1) を選択し、ドキュメント クラスのインターフェイスを弱体化させないように固執しますか?

両方のアプローチについて考えると、(理論的には)任意の関数を静的関数として実装できるという結論に達しました。

Class.Function(aConcreteClassObject, parameters);

非静的でもあります:

aConcreteObject.DoSomething(parameters);

実際の例を挙げると、次のようになります。

[EDIT(パラメータ fromPath を追加「すみません、忘れました」)]

//----- 2) static approach ----------------------------
File.Copy(fromPath, toPath);    // .Net-Framework-like

[/編集]

だけでなく:

//----- 1) non static approach ------------------------
ExampeFileClass fileObject = new ExampleFileClass();
fileObject.Copy(toPath);

または(一種のOOP-Overkill):

//----- 1) non static approach, too -------------------
fileObject.ToPath = @"C:\Test\file.txt";     // property of fileObject
fileObject.Copy();                           // copy to toPath

では、なぜ 1) を使用する (しない) か、または 2) を使用する (しない) のか?

(Document クラスの例にはあまり集中しません。これは、優れたクラス設計に関する一般的な質問だからです。)

4

11 に答える 11

16

どうぞ。

最初に:

そのため、私は静的メソッドを頻繁に使用する傾向があります (具体的なインスタンスから独立するために - 独立性は常に良いことです)。

まったく逆です。静的メソッドを使用する場合、具体的なインスタンスに大きく依存します。

あなたDocumentに関する限り、私はどちらにも行きません。クラスのすべての責任をリストしましたDocument。これには、データの集約、データベースへの保存、ページの操作、およびコピーが含まれます。

これはやり過ぎです。SRPによると、各「モジュール」(ここでは包括的な用語として使用される「モジュール」) には、変更する理由が 1 つだけある必要がありますあなたDocumentには多くの責任があるため、変更する理由はたくさんあります。これはダメです。

それを念頭に置いて、厳密に定義された責任を持つ他のクラスにすべてのロジックを移動します。何を移動するかについて多かれ少なかれ受け入れられている基準は、Herb Sutter または Andrei Alexandrescu のいずれかによって導入されたと私は信じています。問題のオブジェクト。


于 2009-04-28T13:58:01.077 に答える
9

静的メソッドを使用してインターフェイスを実装することはできず、静的メソッドをオーバーライドすることもできません。したがって、静的メソッドを使用するということは、単純に OOP を行っていないことを意味します。

静的メソッドのみを使用して次の機能を実装する方法を考えてみてください。

interface IDocument 
{
   void Print(IDevice targetDevice);
}

IDocument instance;

instance = new PdfDocument();
instance.Print(printer);

instance = new WordDocument();
instance.Print(printer);
于 2009-04-28T14:02:10.817 に答える
8

接吻。コンストラクターを呼び出す必要がない場合は、さらに優れています。

また、静的なメソッドは、関数がどのように動作するかについて少し教えてくれるはずです:

  • 渡されたもの以外の変数では動作しません。
  • メソッドが呼び出されるとき以外はメモリを必要としません (関数から返されるものは数えません)。

他にも注意すべき重要な点がいくつかあります。

  • 一部のインスタンス (Java) の静的メソッドはオーバーライド/サブクラス化できないため、実装を変更する必要がない場合により適しています。
  • 静的メソッドは本質的にテストが難しいと主張する人もいます。

このスレッドと、このトピックに関する膨大な量の議論を率直に提供する単純なグーグル検索も参照します。

于 2009-04-28T13:52:27.313 に答える
6

私の「ルール」は次のとおりです。

  • クラスのプロパティを使用する必要がない場合は、静的にします。(つまり、メソッドが実際にはクラスにアタッチされていない場合、ロジックの関連付けのためだけにあり、 static を使用します)
于 2009-04-28T13:54:10.053 に答える
3

一般に、次のような方法がある場合:

Document.Copy(myDocumentObject, toPath);

ドキュメントである最初のパラメーターは、実際にはドキュメントに対する操作であることを示唆しているため、非静的メソッドを使用する方が良いと思います。

于 2009-04-28T13:54:42.177 に答える
2

一般に、オブジェクト指向の考え方を使用してプログラミングする場合は、静的メソッドの使用を避けたいと思うでしょう。OOPでは、すべてをオブジェクトとして表現し、各オブジェクトにそのコア抽象化を表す明確な機能セットを提供するという考え方があります。静的メソッドは、この抽象化を「破り」ます。

コピーメソッドを使用してDocumentクラスについて説明している例は、その代表的な例です。私は正しいOOの実装が最初の方法であると主張します。つまり、次のようなインスタンスメソッドとしてコピーを作成します。

document1.copy(toPath)

それ自体をコピーする機能がドキュメントのコア抽象化の一部であることは理にかなっています。このように、コピーメッセージを送信するクライアントコードは、コピー先を指定するだけで済みます。これは、ドキュメントが内部の場所を追跡していることが理解されているためです。その情報を他の場所に複製する必要はありません。これは、次のように表示される3番目のオプションの大きな問題です。

Document.copy(fromPath, toPath)
于 2009-05-13T19:42:50.933 に答える
1

静的メソッドは非常に便利です。私は拡張メソッドが大好きですが、結合を強制し、不適切に使用するとテストが悪夢になる可能性があります。

静的を使用する場合の良い例は、検証を行いたい場合です

public static errors Validate(Document myDoc)
{
..some validation code
}

これは非常にテスト可能であり、メソッドをオブジェクトに密結合することは重要ではありません。静的メソッドを使用するのに不適切な場所は、何か他のものを処理してから何かを返す場合です。例としては、オブジェクトを検証する Biz レイヤーがあり、検証に合格した場合はデータを DB に保存します。

public static errors ValidateAndSave(Document myDoc)
{
    errors docErrors = Validate(myDoc);
    if(docErrors.count==0)
    {
         docErrors = SaveToDB(myDoc);
    }

   return docErrors; 
} 

これを実行するたびに、データベースへの検証に合格するため、これをテストするのは本当に苦痛です。Biz ロジックはエラーを生成しない可能性がありますが、DAL レイヤーはエラーを生成する可能性があるため、Biz レイヤーの機能のみをテストするのではなく、また、DALレイヤーもテストする必要があり、オブジェクト、Bizレイヤー、およびDalを緊密に結合して、テストと保守を非常に困難にします.

于 2009-04-28T15:23:31.150 に答える
1

質問する必要がある場合は、静的を使用しないでください。

実際の経験則 (実際には技術的な理由がたくさんありますが、これは概念を説明するのに役立ちます):

  • 問題のクラスが複数回存在できる場合、それは静的ではありません。

  • 問題のメソッドがインスタンス情報に対して動作する場合、それは静的ではありません。

  • メソッドまたはクラスがメタ情報に関するものである場合、それは静的です。

これらのガイドラインにより、ファイルとドキュメントは倍数であり、コピーはインスタンスに対する行為であることは明らかです。メソッドは静的であってはなりません。

于 2009-04-28T14:08:39.333 に答える
0

altCongnito と同じですが、fileObject.Copy というオブジェクトを追加します。クラスとの理想的な関係を持ち、関数の依存関係がない関数の静的。

于 2009-04-28T13:56:46.053 に答える
0

一般に、オブジェクトに関する限り、自分自身を「コピーする」とは、通常、自分のデータを新しいオブジェクトに複製することを意味します。ここで説明する「コピー」は、オブジェクトではなく、ファイルシステムがユーザーに代わって行うことです。そのため、Document インスタンスのメソッドではなく、静的メソッドにします。

于 2009-04-28T13:54:54.560 に答える