ここでいくつかの質問に答えながら、最近私が行っているいくつかの作業から、なぜJavaが組み込みクラスのメソッドチェーンをサポートしていないのか疑問に思っています。
たとえばCar
クラスを作成する場合、次のようにvoidの代わりにthis
を再実行することでchainableにすることができます。
public class Car {
private String make;
public Car setMake(String make) {
this.make = make;
return this;
}
}
組み込みライブラリがこのようにしない傾向がある特別な理由はありますか?メソッドチェーンの欠点はありますか?
私はメソッドチェーンの欠如を説明する何かを見落としたかもしれませんが、デフォルトでvoidを返すすべてのセッターメソッドはthisへの参照を返す必要があります(少なくとも私の目はそれをすべきです)。これにより、次のような状況がよりクリーンになります。
container.add((new JLabel("label text")).setMaximumSize(new Dimension(100,200)));
より長いものではなく:注:必要に応じて、この方法でコーディングすることを妨げるものではありません。
JLabel label = new JLabel("label text");
label.setMaximumSize(new Dimension(100,200));
container.add(label);
私はこの決定の背後にある理由を聞いて非常に興味があります。私が推測しなければならない場合、これに関連するオーバーヘッドがあるため、必要な場合にのみ使用する必要があります。
ええ両方向で読みやすさの議論があります-一行に多くを入れようとするようなものがあります。
しかし、正直に言って、これは歴史的な理由によるものだと思います。スイングが開発されていました。これは後で追加されるべきだと主張することもできますが、そのようなことは、バイナリの非互換性や、Sun/Oracleが歴史的に非常に慎重にしてきた他の問題を引き起こす傾向があります。
最新のJDKライブラリ-たとえば、 ByteBuffer
メジャーなよく知られた例-haveは、連鎖動作などを提供します。それは理にかなっている。
私が考えることができるもう1つの理由はperformance、またはより正確には、使用しないものにお金を払わないことです。各メソッドの後のreturn this
はそれほど高価ではありませんが、追加のCPUサイクルがほとんどなく、1つのCPUレジストリが必要です。
void
戻り値を宣言するすべてのメソッドに暗黙のreturn this
を追加するというアイデアさえありましたが、拒否されました。
本当の理由については推測することはできますが、厳密に言えば、それは非常にオブジェクト指向ではない可能性があります。
モデル化された世界のアクションを表すアクションとしてメソッドを表示する場合、メソッドチェーンはその図に実際には適合しません。
もう1つの理由は、チェーンメソッドをオーバーライドしようとしたときに発生する可能性のある混乱です。この状況を想像してみてください:
_class Foo {
Foo chainedMethod() {...}
}
class Bar extends Foo {
Foo chainedMethod() {...} //had to return Foo for Java versions < 1.5
void doStuff();
}
_
したがって、new Bar().chainedMethod().doStuff()
を実行しようとすると、コンパイルされません。そして、_((Bar)new Bar().chainedMethod()).doStuff()
_は見栄えがよくありません:)
メソッドチェーンは通常、Builderパターンで使用され、StringBuilder
クラスで確認できます。それ以外では、メソッドチェーンによってコマンドと作成の分離が不明確になる可能性があります。たとえば、repaint()
もFluentインターフェイスの一部にする必要がありますか?それから私は持つことができました:
container.add(label).repaint().setMaximumSize(new Dimension(100,200)));
突然、呼び出しの順序が重要になり、メソッドチェーンに隠れてしまう可能性があります。
メソッドチェーンを実装しない理由は、次のようなものです。
メソッドチェーンの最大の問題は、仕上げの問題です。回避策はありますが、通常、この問題が発生した場合は、ネストされた関数を使用した方がよいでしょう。ネストされた関数は、コンテキスト変数に混乱している場合にも適しています。
チェーンの外のオブジェクトが実際に有効なnull以外のオブジェクトを返す保証はありません。また、多くの* IDE *はデバッグ時にメソッド呼び出しを検査可能なオブジェクトとして評価しないため、このスタイルのコードのデバッグは、多くの場合非常に困難です。
他のクラスのルーチンを呼び出して引数をチェーンメソッドの1つに渡す場合、主に行が非常に長くなるために渡すパラメータが多い場合、混乱する可能性があります。
パフォーマンスの問題もあります。これは、メモリに集中して動作します
あなたは本当に デメテルの法則 について尋ねています
「直接の友達とだけ話す」
上記のリンクは素晴らしいリソースですが、そこで長い時間を過ごすと、探していた答えが得られないことに注意してください。 :-)