2

戻り値のあるメソッドを作成するときは、通常、デフォルト値を返さなければならないような方法でメソッドが呼び出されないように設定します。私が始めたとき、私はしばしば何かをするメソッドを書き、それらがしたことを返すか、何かをしなかった場合はnullを返しました。しかし、コード全体に醜いif(!null)ステートメントがあるのは嫌いです。

実用的なプログラマーが何ヶ月も前に読んだルビーのリガイドを読んでいますが、通常は何も返さないのに、しばしば戻ってくるself(ruby's )ことに気づきました。thisこれは、この例のように、属性を設定したオブジェクトを返すセッターを使用して、メソッド呼び出しをチェーンできるようにするためであると彼らは言います。

tree.setColor(green).setDecor(gaudy).setPractical(false)

最初は、この種のものが魅力的だと思います。メソッド呼び出しをチェーンできることに喜びを感じたことが何度かありますが、Player.getHand().getSize()これは、メソッド呼び出しのオブジェクトがステップごとに変わるという点で多少異なります。

Stack Overflowは戻り値についてどう思いますか?戻り値を考えるときに心に浮かぶパターンやイディオムはありますか?欲求不満を避けて美しさを増すための素晴らしい方法はありますか?

4

4 に答える 4

5

私の謙虚な意見では、考慮すべき3種類の返品ケースがあります。

オブジェクトプロパティの操作

1つは、オブジェクトプロパティの操作です。ここで説明するパターンは、オブジェクトを操作するときによく使用されます。非常に典型的なシナリオは、工場と一緒に使用することです。この架空の作成呼び出しを考えてみましょう。

// When the object has manipulative methods:
Pizza p = PizzaFactory().create().addAnchovies().addTomatoes(); 
// When the factory has manipulative methods working on the 
// object, IMHO more elegant from a semantic point of view:
Pizza p = PizzaFactory().create().addAnchovies().addTomatoes().getPizza();

メソッドは人間が読める形式の1つを形成するため、正確に何が作成されているのか、またはオブジェクトがどのように操作されているのかをすばやく把握できます。それは間違いなく素晴らしいですが、使いすぎないでください。経験則では、これは、戻り値をvoidとして宣言することもできるメソッドで使用される可能性があります。

オブジェクトのプロパティの評価

2つ目は、メソッドがオブジェクトの何かを評価する場合です。たとえば、car.getCurrentSpeed()現在の速度を要求してそれを返すオブジェクトへのメッセージとして解釈できるメソッドについて考えてみます。複雑すぎず、単に値を返すだけです。:)

オブジェクトにこれまたはそれを実行させる

3つ目は、メソッドが操作を実行し、呼び出し元の意図がどの程度満たされたかを示す何らかの値を返す場合ですが、そのようなメソッドをレイアウトするのは難しい場合があります。

int new_gear = 20;
if (car.gears.changeGear(new_gear)) // does that mean success or fail?

ここで、メソッドの設計が難しいことがわかります。成功または失敗したときに0を返す必要がありますか?車のギアが5つしかないため、ギアを設定できなかった場合は-1はどうですか?それは現在のギアも-1になっているということですか?メソッドは、変更したギアを返す可能性があります。つまり、メソッドに提供された引数を戻りコードと比較する必要があります。それはうまくいくでしょう。一方、失敗の場合はtrueまたはfalseを返し、失敗の場合はfalseまたはtrueを返すことができます。これらのメソッド呼び出しが失敗するか成功するかを見積もることで、どちらを使用するかを決定できます。

私の謙虚な意見では、そのような戻り値のセマンティクスをセマンティックな説明を与えることによって、より適切に表現する方法があります。オブジェクトを操作する将来の開発者は、メソッドのコメントやドキュメントを検索する必要がないため、あなたを気に入るはずです。

class GearSystem {
// (...)
public:
enum GearChangeResult
{ GearChangeSuccess, NonExistingGear, MechanicalGearProblem };

GearChangeResult changeGear (int gear);
};

そうすれば、コードを見ているプログラマーにとって、戻り値が何を意味するのかが完全に明らかになります(if (gears.changeGear(20) == GearSystem::GearChangeSuccess)上記の例よりもはるかに明確になります)。

アンチパターン:リターンコードとしての失敗。

私の意見ではそうではないので、私が実際に省略した戻り値の4番目の可能性:論理エラーや処理する必要のある障害など、プログラムにエラーがある場合、理論的には次のような値を返すことができます。それで。しかし、今日では、それはもうそれほど頻繁には行われていません(または行われるべきではありません)。そのために、例外があります。

于 2008-12-26T11:22:35.323 に答える
1

メソッドがnullを返さないことに同意しません。最も明白な例は、システムプログラミングからのものです。たとえば、誰かがファイルを開くように要求した場合、開くことが失敗した場合は単にnullを指定する必要があります。正気の代替手段はありません。リンクリストの最後のノードで呼び出されたときに、getNextNode(node)メソッドなど、nullが適切な場合もあります。したがって、これらのケースに共通しているのは、nullが「オブジェクトなし」(ファイルハンドルなしまたはリストノードなし)を表すということだと思います。これは理にかなっています。

それ以外の場合、メソッドは失敗しないはずであり、適切な例外機能があります。そうすれば、あなたの例のようなメソッドチェーンが非常に効果的に使用できると思います。これが「実用的なプログラマー」の革新であるとあなたが信じているように見えるのは少しおかしいと思います。実際、それは以前ではないにしてもLispにまでさかのぼります。

于 2008-12-26T11:19:56.530 に答える
1

戻りthisは「ビルダーパターン」でも使用されます。これは、メソッドチェーンが読みやすさと書き込みの利便性を向上させる別のケースです。

多くの場合、結果を生成できなかったことを示すために、範囲外の値として null が返されます。結果が得られないことが通常のイベントである場合、これは完全に合理的であると私は信じています。例には、readLine()ファイルの終わりでの null の戻り、または のget(...)メソッドに存在しないキーを提供するときに返される null が含まれますMap。ファイルの最後まで読み取るのは通常の動作です (読み取り中に異常が発生したことを示す IOException とは対照的です)。同様に、キーを調べて値がないと言われるのは、通常のケースです。

場合によっては、null の適切な代替手段は「null オブジェクト」です。これは、結果クラスの完全なインスタンスですが、「誰も家にいない」場合に適した状態と動作を備えています。たとえば、存在しないユーザー ID を検索した結果、名前の長さがゼロで、システム内で何もする権限がない NullUser オブジェクトになる可能性があります。

于 2008-12-26T17:12:19.077 に答える
0

それは私を混乱させます。オブジェクト指向プログラミング言語には、Smalltalkのセミコロンが必要です。

tree color: green;
     decor: gaudy;
     practical: false.

obj method1; 方法2。「objでmethod1を呼び出し、次にobjでmethod2を呼び出す」という意味です。この種のオブジェクト設定は非常に一般的です。

于 2008-12-26T11:22:21.063 に答える