クロージャがクラスよりも強力であることがわかりません。クラスを使用して、クロージャと同じ動作を実現できるようです。どんな助けでもいただければ幸いです
5 に答える
クロージャーは貧乏人の物 / 物は貧乏人のクロージャー
参照してください:クロージャーとオブジェクト
怠け者のために:
由緒あるマスターQc Naは、彼の学生、アントンと一緒に歩いていました。マスターに議論を促したいと思って、アントンは「マスター、オブジェクトはとても良いものだと聞きましたが、本当ですか?」と言いました。Qc Na は同情するように彼の生徒を見て、「愚かな生徒 - オブジェクトは単に貧乏人の閉鎖です。」 と答えました。
懲らしめられたアントンは、主人から離れて独房に戻り、閉鎖を研究することに専念しました。彼は「Lambda: The Ultimate...」シリーズの論文とその関連文書全体を注意深く読み、クロージャベースのオブジェクト システムを備えた小さな Scheme インタープリタを実装しました。彼は多くのことを学び、主人に進捗状況を報告することを楽しみにしていました。
次の Qc Na との散歩で、アントンは主人に感銘を与えようと、「マスター、私はこの問題を熱心に研究しましたが、オブジェクトは本当に貧しい人の閉鎖であることがわかりました」と言いました。Qc Na は、Anton をスティックで叩いて、「いつ学習しますか? 閉鎖は貧乏人の目的です」と答えました。その瞬間、アントンは悟りを開いた。
—<a href="http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html" rel="nofollow noreferrer">Anton van Straaten
Aclosure
とaclass
は2つの非常に異なるものです。
class
「AはAよりも強力である」と言うのは正しくありませんclosure
。またはその逆。
彼らは全く異なることをします。
Aclosure
は基本的な意味で、作成されたスコープからのローカル変数情報を保持する関数呼び出しです。
Aclass
はオブジェクトの定義です。このクラスは、クラスのインスタンスの動作と内容を定義します。
クラスとクロージャの違いは、すでに他の人によって説明されています。Java API の多くの場所で、それらをサポートする言語がクロージャーを使用する/使用できる場合、インターフェースの匿名実装が使用されていることを指摘したかっただけです。たとえば、次のコードを考えてみましょう。
JButton btn = new JButton("Say Hello");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageBox("Hello");
}
});
この場合、匿名の ActionListener はクロージャーとして機能していると言えます。Java がクロージャーを許可している場合、コードは次のようになります: (c++0x 風の構文を使用)
JButton btn = new JButton("Say Hello");
btn.addActionListener([]=>(ActionEvent e){JOption.showMessageBox("Hello");});
この些細なケースでは、クロージャとインターフェイスの匿名実装 (AII) の主な違いは次のとおりです。
- AII メソッドは、クロージャーよりも強力な型チェックを行います。(クロージャーシステムはより強力な型チェックを持つようにすることができますが、一般的にはそうではありません)
- クロージャー構文では、入力が少なくて済みます。これは、Java の必要なクロージャー引数を十分に長く噛むと明らかになる主な不満のようです。
私は、AII が必要なことを実行できない状況にまだ遭遇していません。はい、定義するタイピングと別のインターフェイスがありますが、それらはシステムが機能し、私見では、AII を使用する必要がなく、独自のメソッド、メンバー データ、およびコンストラクターを備えた本格的なクラスを使用できるため、より強力です。 . 例として、コンテキスト メニューをポップアップするアクション リスナーがあります。ActionListener を実装し、JMenu を引数として取るクラスを作成すると、次のことが可能になります。
btn.addActionListener( new ContextMenuActionListener(myMenu) );
これは、boost:bind タイプのソリューションよりも (私には) きれいに見えます。
[]=>(ActionListener) myContextPopupClosure = []=>(ActionListener E){ ... };
...
btn.addActionListener( Closure.bind1(myContextPopupClosure,myMenu) );
とか、ぐらい
編集:
昨夜ジェネリックをいじって多くの作業を行った後、AII に対するクロージャーの利点の 1 つに気付きました。上記の例では、クロージャが []=>(ActionEvent) 型であると想定していましたが、実際には []=>(? super ActionEvent) 型である可能性があります。これの意味は:
[]=>(Object) c = []=>(Object o) { System.exit(0); }
btn.addActionClosure( c );
window.addMouseMovedClosure( c );
//Each method in MouseMotion listener would need it's own closure.
//So I 'invented' an API change.
コンパイル可能になります。これは、複数のイベントに対応して同じことを行う必要がある場合に役立ちます。
もう一つの例。このクロージャーは、クロージャーを取る任意の場所に追加できます。ActionListener または MouseListener として何かに追加すると、呼び出しがログに記録されます。
[]=>(Object ... objs) log = []=>(Object ... obj) {for(Object o:obj){logObject(o);}}
これは良い質問ですが、より適切な言葉遣いになる可能性があります。
「Java オブジェクトと JavaScript クロージャーの類似点と相違点は何ですか?」
類似点: どちらもローカル変数に永続的な状態があります。それらのメソッドは、これらの状態変数にアクセスできます。
相違点: Javascript は関数型言語であるため、関数内の関数をすぐに呼び出して返すことができます。例えば:
newXY = function(x,y) {
var that = {};//Instantiate new object
var x = parseFloat(x);
var y = parseFloat(y);
that.xtimesy = function() {
return x*y;
}(); // <-- Notice the immediate invocation of the function, here.
return that;
};
したがって、このスニペットのコピー/ rhino shellから貼り付けたようなコードを書くことができます:
js> var foo = newXY(2,5);
js> foo.xtimesy;
10