web-dev-qa-db-ja.com

「閉鎖は貧乏人のオブジェクトであり、逆もまた同様」-これはどういう意味ですか?

閉鎖は貧乏人の目的であり、その逆も同様です。

私はこの声明を見ました atmanyplaces ウェブ上( SOを含む )しかし私は完全には理解していませんその意味。誰かがそれが正確に何を意味するのか説明してもらえますか?

可能であれば、回答に例を含めてください。

57
missingfaktor

オブジェクトは貧乏人の閉鎖です。

Javaについて考えてみましょう。 Javaは、実際の字句クロージャを言語レベルでサポートしないオブジェクト指向プログラミング言語です。回避策としてJavaプログラマは、閉じることができる匿名の内部クラスを使用します。字句スコープで使用可能な変数を超えます(それらがfinalである場合)。この意味で、オブジェクトは貧弱な人間のクロージャです。

閉鎖は貧乏人の物です。

Haskellを考えてみましょう。 Haskellは関数型言語であり、実際のオブジェクトに対する言語レベルのサポートはありません。ただし、クロージャを使用してモデル化できます。これは、Oleg KiselyovとRalf Lammelによる優れた論文 this で説明されています。この意味で、クロージャーは貧乏人の目的です。


OOバックグラウンドから来た場合、おそらくオブジェクトの観点から考えるのがより自然であり、したがって、それらをクロージャーよりもより基本的な概念と考えるかもしれません。 FP背景、クロージャーの観点から考える方が自然であると感じるかもしれません。したがって、それらをオブジェクトよりも基本的な概念と考えるかもしれません。

物語の教訓は、クロージャーとオブジェクトはお互いに表現できるアイデアであり、他のものより基本的なものはないということです。検討中のステートメントはこれですべてです。

哲学では、これは モデル依存のリアリズム と呼ばれます。

60
missingfaktor

重要なのは、クロージャとオブジェクトが同じ目標を達成するということです。つまり、データや機能を単一の論理ユニットにカプセル化することです。

たとえば、次のように犬を表すPythonクラスを作成できます。

_class Dog(object):
    def __init__(self):
        self.breed = "Beagle"
        self.height = 12
        self.weight = 15
        self.age = 1
    def feed(self, amount):
        self.weight += amount / 5.0
    def grow(self):
        self.weight += 2
        self.height += .25
    def bark(self):
        print "Bark!"
_

そして、クラスをオブジェクトとしてインスタンス化します

_>>> Shaggy = Dog()
_

Shaggyオブジェクトには、データと機能が組み込まれています。Shaggy.feed(5)を呼び出すと、彼は1ポンド増えます。そのポンドは、オブジェクトの属性として格納される変数に格納されます。これは、多かれ少なかれ、オブジェクトの内部スコープにあることを意味します。

Javascriptをコーディングしている場合は、次のようなことを行います。

_var Shaggy = function() {
    var breed = "Beagle";
    var height = 12;
    var weight = 15;
    var age = 1;
    return {
        feed : function(){
            weight += amount / 5.0;
        },
        grow : function(){
            weight += 2;
            height += .25;
        },
        bark : function(){
            window.alert("Bark!");
        },
        stats : function(){
            window.alert(breed "," height "," weight "," age);
        }
    }
}();
_

ここでは、オブジェクト内にスコープを作成する代わりに、関数内にスコープを作成して、その関数を呼び出しました。この関数は、いくつかの関数で構成されるJavaScriptオブジェクトを返します。これらの関数はローカルスコープで割り当てられたデータにアクセスするため、メモリは解放されないため、クロージャーによって提供されるインターフェイスを通じて引き続き使用できます。

57
BenTrofatter

オブジェクトは、最も簡単に言えば、状態とその状態で動作する関数の単なるコレクションです。クロージャは、状態とその状態で動作する関数のコレクションでもあります。

コールバックを受け取る関数を呼び出したとしましょう。このコールバックでは、関数呼び出しの前にわかっている状態を操作する必要があります。この状態(「フィールド」)を具体化し、コールバックとして実行するメンバー関数(「メソッド」)を含むオブジェクトを作成できます。または、すばやく簡単な(「貧乏人の」)ルートを使用してクロージャーを作成することもできます。

オブジェクトとして:

class CallbackState{
    object state;

    public CallbackState(object state){this.state = state;}

    public void Callback(){
        // do something with state
    }
}

void Foo(){
    object state = GenerateState();
    CallbackState callback = new CallbackState(state);
    PerformOperation(callback.Callback);
}

これは疑似C#ですが、他のOO言語と概念が似ています。ご覧のとおり、状態を管理するためのコールバッククラスに含まれるボイラープレートはかなりあります。これはクロージャを使用する方が簡単:

void Foo(){
    object state = GenerateState();
    PerformOperation(()=>{/*do something with state*/});
}

これはラムダです(これもC#構文ですが、クロージャをサポートする他の言語でも概念は似ています)。別のクラスを作成、使用、維持することなく、クラスのすべての機能を提供します。

また、「オブジェクトは貧乏人の閉鎖である」という当然の結果も聞こえます。クロージャーを利用できない、または利用しない場合、最初の例のように、オブジェクトを使用して作業を行わざるを得ません。オブジェクトはより多くの機能を提供しますが、すでに述べた理由により、クロージャーが機能する場合はクロージャーの方が適していることがよくあります。

したがって、オブジェクトのない貧しい人はクロージャーで仕事を成し遂げることができ、クロージャーのない貧しい人はオブジェクトを使って仕事を成し遂げることができます。金持ちは両方を持っており、仕事ごとに適切なものを使用しています。

14
P Daddy

編集済み:質問のタイトルに「その逆」が含まれていないため、質問者の意図を想定しないようにします。

2つの一般的な陣営は、関数型言語と命令型言語です。どちらも、さまざまな方法でさまざまな方法で同様のタスクを実行できるツールです。

クロージャーは貧乏人の物です。

オブジェクトは貧乏人の閉鎖です。

個々に、それぞれの発言は通常、作者が何らかのバイアスを持っていることを意味します。バイアスがない場合は、どちらかの環境に制約されている可能性があります。私が読んだ著者は、この種のものは通常、熱心な、純粋主義者、または言語の宗教的なタイプであると言っています。可能であれば、言語の宗教的なタイプは避けます。

クロージャは貧乏人のオブジェクトです。オブジェクトは貧乏人のクロージャです。

その作者は「実用主義者」であり、またかなり賢いです。それは、作者が両方の観点を高く評価し、それらが概念的に同一であるということを高く評価することを意味します。これは私の一種の仲間です。

7
codenheim

クロージャーがスカートの下にある匿名のオブジェクトを隠すので、砂糖はそれほど多くありません。

6
DaGreek

「オブジェクトは貧乏人のクロージャです」は、理論上の同等性を表明するだけではありません。これは一般的なJavaイディオムです。匿名クラスを使用して、現在をキャプチャする関数をまとめるのは非常に一般的です。状態。使用方法は次のとおりです。

_public void foo() {
    final String message = "Hey ma, I'm closed over!";
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            System.out.println(message);
        }
    });
}
_

これは、別の言語でクロージャーを使用した同等のコードによく似ています。たとえば、Objective-Cブロックを使用する(Objective-CはJavaにかなり似ているため)。

_void foo() {
    NSString *message = @"Hey ma, I'm closed over!";
    [[NSOperationQueue currentQueue] addOperationWithBlock:^{
        printf("%s\n", [message UTF8String]);
    }];
}
_

唯一の本当の違いは、機能がJavaバージョンのnew Runnable()匿名クラスインスタンスにラップされていることです。

5
Chuck