web-dev-qa-db-ja.com

カプセル化と情報隠蔽

カプセル化と情報隠蔽の違いは何ですか?

まあ私はフィールドをプライベートにし、フィールドのセッターとゲッターをカプセル化することがカプセル化であることを知っていますが、カプセル化はこれだけを意味しますか?

以下に説明するクラスがあるとします。

public Class IsThisEncapsulation
{
    public int age;

    public void setAge(int age)
    {
       this.age=age;
    }

    public int getAge()
    {
       return age;
    }
}

クラスIsThisEncapsulationはカプセル化の例ですか?

今、上記のクラスのフィールド「年齢」をプライベートにすると、情報の隠蔽が実現しますか?

これらの概念を明確に区別するのに役立つ明確な例を教えてください。

19
user1720616

フィールドをプライベートにしてから、フィールドのセッターとゲッターをカプセル化することはわかっています。しかし、カプセル化はこれだけを意味するのでしょうか?

--->カプセル化はOOP概念であり、オブジェクトの状態(クラスフィールド)とその動作(メソッド)が一緒にラップされます。Javaは、classを使用してカプセル化を提供します。

情報非表示:

->オブジェクトの一部のコンポーネントへのアクセスを制限するメカニズム。上記の例は、ageをプライベートにすると情報が非表示になる場合です。


当初、情報/データ隠蔽はカプセル化の一部と見なされていました。カプセル化の定義は次のようになります。

  • オブジェクトのコンポーネントの一部へのアクセスを制限するための言語メカニズム。
  • データを操作するメソッド(または他の関数)とデータのバンドルを容易にする言語構造。

2番目の定義は、多くのOOP言語ではコンポーネントの非表示が自動的ではないか、またはオーバーライドできるため、2番目の定義を好む人が別の概念として情報の非表示を定義するという事実によって動機付けられています。 。

リファレンス: wikipage

17

From abstraction-vs-information-hiding-vs-encapsulation から

抽象化とカプセル化は補完的な概念です:抽象化はオブジェクトの観察可能な動作に焦点を当てています...カプセル化はこの動作を引き起こす実装に焦点を合わせています...カプセル化はほとんどすべての情報を隠すプロセスである情報の非表示によって達成されますその本質的な特性に寄与しないオブジェクトの秘密。

情報非表示:

「そのインターフェースまたは定義は、その内部の仕組みについてできる限り明らかにしないように選択されました。」 — [パルナス、1972b]

「抽象化は、どの情報を非表示にするかを識別するための手法として使用できます。」

「混乱は、情報の非表示と、どの情報を非表示にするかを特定するのに役立つ手法(抽象化など)を区別できない場合に発生する可能性があります。」

カプセル化:

「[…]は、いくつかのコレクションの周りにカプセルを構築することを指します。 — [Wirfs-Brock et al、1990]

「プロセスとしてのカプセル化とは、1つまたは複数のアイテムを[…]コンテナ内に封入する行為を意味します。カプセル化とは、エンティティとして、1つまたは複数のアイテムを保持(包含、封入)するパッケージまたはエンクロージャを指します。」

「カプセル化が「情報の隠蔽と同じもの」だったとしたら、「カプセル化されたものもすべて隠されている」という主張をするかもしれません。これは明らかに真実ではありません。」

8
Sumit Singh

カプセル化と情報の隠蔽は、密接に関連している概念ですが、正確な定義は、話し相手によって異なります。

「情報の非表示」の概念は、システムの相互接続性を低下させるために情報へのアクセスを制限する必要があると提案した Parnas(1971) によって最初に説明されました。ユーザーフレンドリーな外部インターフェイスを維持しながら、システムをモジュールに分割し、クライアントに影響を与えることなく実装の詳細を変更できるようにすることを提案しました。

「カプセル化」という用語は、システムの複雑さを軽減し、危険な変更からデータを保護するために、基になるデータへのアクセスを制御する手順の使用を説明するために Zilles(1973) によって造語されました。

その後、 Parnas(1978) は、情報の非表示とカプセル化(および抽象化)を同義語として説明し、変更される可能性のあるシステムの詳細の非表示を説明しました。ただし、 Micallef(1987) のように、情報の非表示とカプセル化は区別されています。 Cohen(1984)Abreu and Melo(1996) などの一部の著者は、特にオブジェクト指向プログラミング言語で、情報の隠蔽を可能にする「カプセル化メカニズム」について説明しています。

Meyers(2000) は、コードの一部がカプセル化される程度は、変更された場合に破損するコードの量に依存することを示唆しています。この意味で、プライベートデータとメソッドは、アクセスできるメソッドが少ないほどカプセル化されます。対照的に、公開データとメソッドは、アクセスできるコードの量が不明であるため、完全にカプセル化されていません。

逆に、 Rogers(2001) は、カプセル化が、データを操作するメソッドとデータをバンドルできるようにする言語メカニズムにすぎないことを示唆しています。彼は、カプセル化は基本的に情報の隠蔽とは関係がないと主張しています。しかし、この定義は、彼の論文が発表される前の28年間の学術文献におけるほとんどすべての用語の使用に反しています。そこにareこの使用法の他のいくつかの例、たとえば Archer and Stinson(1995) がありますが、それらはほとんどありませんとの間で特に注目に値しません。

結論として、情報の非表示は、クライアントに影響を与えずにデザインを変更できるように、情報を非表示にする必要があるという考えです。これにより、柔軟性と堅牢性が向上します。カプセル化は情報の隠蔽と同じであると見なすことができますが、この用語は、特にオブジェクト指向プログラミングにおける情報の隠蔽の実際的な実装を説明するためによく使用されます。

情報の非表示/カプセル化の例として、次のクラスを検討してください:

public class BankAccount {
    public int dollars;
}

このクラスの実装は完全にカプセル化されていません。つまり、柔軟性がなく(たとえば、個々のセントのサポートを将来簡単に追加することはできません)、安全ではありません(たとえば、アカウントをマイナスに変更できます)。ただし、メソッドの正式に定義されたインターフェースの背後にデータを隠すと、柔軟性と安全性が得られます。

public class BankAccount {
    private int dollars;

    public void deposit(int dollars) {
        this.dollars += Math.max(0, dollars);
    }
}

これで状態の変更方法を制御でき、クライアントコードを壊すことなく実装を変更することもできます。

public class BankAccount {
    private int cents;

    public void deposit(int dollars) {
        deposit(dollars, 0);
    }

    public void deposit(int dollars, int cents) {
        this.cents += Math.max(0, 100 * dollars) + Math.max(0, cents);
    }
}

基礎となる実装に関する情報が隠されているため、クラスのカプセル化が改善されました。

5
Joseph Thomson

それらの間には微妙な違いがあります。私はSteve FreemanとNat Pryceによって書かれた「Growing Object-Oriented Software Guided Tests by Tests」からの説明が好きです。

それは言う:

カプセル化

オブジェクトの動作がそのAPIを介してのみ影響を受けることを保証します。無関係なコンポーネント間に予期しない依存関係がないことを保証することにより、1つのオブジェクトへの変更がシステムの他の部分にどの程度影響を与えるかを制御できます。

情報の非表示

オブジェクトがそのAPIの抽象化の背後にある機能を実装する方法を隠します。これにより、当面のタスクに関連しない下位レベルの詳細を無視することにより、高度な抽象化で作業できます。

5
Eds

文字通りの意味を見てください。カプセル化は、物をバッグに入れるだけです。つまり、すべての属性とメソッドをクラスに入れるとカプセル化が実現しますが、ある程度、カプセル化によって情報を隠すこともできます。アクセス修飾子はカプセル化ではなく、情報の隠蔽に貢献します。

1

これは、情報の非表示、カプセル化、またはそれが呼び出すものを実装しない場合に起こります。独立していると思うコーナーのどこかで何かを変更すると、悪いことが起こります。次に、システムで使用されているサードパーティのライブラリを変更する場合、システム全体にリファクタリングを行わないと移動できない参照があることがわかります。たとえば、データアクセスライブラリのバージョンをアップグレードしたい(ODP.netバージョンを更新したいときにこの問題に直面した)場合、DBへの参照があるはずのDataAccessクラスを変更したいと考えています。クライアントライブラリ。しかし、すべてのビジネスクラスがDBクライアントライブラリの参照を作成していることがわかります。今度は、1つではなく60個のアセンブリの参照を更新する必要があります:( 情報漏洩

内部ロジックをクライアントに公開するときにも同じことが起こります。たとえば、 "A"、 "B"を有効なフラグとして受け入れ、関数内でロジックを実行する関数EnrollMember(string flag)があるとします。この機能を後で変更する場合、クライアントに通知しないと変更できません。

0

あなたの質問に答えるには:

情報の非表示:内部で実装される方法を公開するオブジェクトの重要な部分を非表示にし、より高い抽象化を公開します。たとえば:テレビのリモコンでは、テレビとやり取りするためのキーだけが表示されます。内部に何が入っているかはわかりません。

カプセル化:カプセル化は、データとメソッドを組み合わせ、内部メソッドにパブリックメソッドからアクセスできるようにします。だから、はい、あなたのクラスで変数ageをprivateにすると、カプセル化が達成されます

0
stamhaney

単純化しすぎた例:

class NoEncapsulationOrInformationHiding { 
   public ArrayList widths = new ArrayList();
}

class EncapsulationWithoutInformationHiding {
   private ArrayList widths = new ArrayList();
   public ArrayList getWidths(){
    return widths;
  }
}

class InformationHidingWithoutEncapsulation {
   public List widths = new ArrayList();
}

class EncapsulationAndInformationHiding{
  private ArrayList widths = new ArrayList();
  public List getWidths(){
    return widths;
  }
}

Encapsulationを使用すると、自分の内部へのアクセスを確認し、そのようなアクセスを実行する特定の方法を提供できます。リークする実装の詳細には特に対処していません。その変数へのアクセスは制御できますが、後でLinkedListを使用することを決定した場合でも、ArrayListを使用してクライアントがあなたを知っているという事実を制御することはできなくなります。

一方、情報の非表示は、ArrayListを使用して幅を実装するという事実を非表示にします。クライアントはそれを実装する方法(InformationHidingIsNotInformationErasing)を見つけることができますが、その実装をサポートする責任はなくなります。続きを読む ここ