ここでの主な問題は、カプセル化が厳密に定義された概念ではなく、なぜそれが有用なのかということです。いくつかの調査を行うと、カプセル化を人々がどのように見るかは非常に意見が分かれており、多くの人々はそれを抽象化と混同していることを示しています。
最初に見つける定義は
カプセル化は、データとデータを操作する関数を結合する概念です...
これがあなたの定義である場合、ほとんどの言語は、データとそのデータで動作する関数をクラス、モジュール、ライブラリ、名前空間などにグループ化する方法を持っています。
しかし、その定義が続くので、それはカプセル化の主な目的ではないと主張します。
...そして、それは外部の干渉と誤用の両方から安全を保ちます。
ウィキペディアもそれに同意します:
オブジェクトのコンポーネントの一部への直接アクセスを制限するための言語メカニズム。
しかし今、私たちは「干渉と誤用」が何を意味するのか、そしてなぜデータへの直接アクセスが制限されるべきなのかを尋ねる必要があります。理由は2つあると思います。
1つ目は、データを変更できる範囲を制限することは、開発者の最大の利益になるということです。あまりにも多くの場合、値が設定される前/後にロジックを持つ必要があります。そして、値を設定できる場所の数が限られていることは非常に貴重です。OOP言語では、これはクラスを使用して行うことができます。「可変」関数型言語では、クロージャは同じ目的を果たします。そして、私たちはclasses = Closuresを知っているので、変更可能な関数型言語はOOPとは「パラダイム」が異なるため、議論の余地があります。
しかし、不変言語についてはどうでしょうか?変数を変更する問題はありません。ここで2番目の問題が発生します。関数とデータをバインドすると、そのデータを有効な状態に保つことができます。の不変の構造を想像してくださいEmail
。この構造には単一のstring
フィールドがあります。タイプの値がある場合Email
、そのフィールドには有効な住所が含まれている必要があります。OOPのカプセル化ではprivate
、そのフィールドを宣言し、Get
メソッドのみを提供し、constructor method
文字列で渡されたものが有効なアドレスである場合にのみ成功します。クロージャーについても同様です。さて、不変言語の場合、構造は特定の関数を介してのみ初期化でき、そのような関数は失敗する可能性があると言う方法が必要になります。そして、私はその基準に合う言語を知りません(たぶんコメントの誰かが私を啓発するかもしれません)。
最後の問題は、カプセル化を「サポートする」言語が意味するものです。一方には、カプセル化の強制を許可する言語があるため、カプセル化が壊れている場合、コードはコンパイルされません。反対に、言語はカプセル化を行う方法を提供するかもしれませんが、それはそれを強制しません、開発者がそれを自分で強制することを残します。2番目のケースでは、構造と関数を持つ任意の言語が機能します。動的言語とHaskellが思い浮かびます。そして、私はスペクトルの反対側に該当する言語は多くはないと思います。オブジェクトのカプセル化を強制するのに非常に優れているC#でも、リフレクションを使用してバイパスできます。しかし、C#で見た場合、大量のコードのにおいであると見なされ、健全なC#開発者が喜んでそうすることはありません。