読者です 読者をやめる 読者になる 読者になる

カプセル化、情報隠蔽、データ隠蔽

あちこちのサイトを見てると、間違った解釈をしてるのが多い。カプセル化なんて、情報隠蔽まで含んでるのが常識になりつつあるような。。。ここまで一般化してると情報隠蔽してるのがカプセル化というのが常識なのかも。

カプセル化・情報隠蔽・データ抽象化 - 今日の役に立たない一言 − Today’s Trifle! −

カプセル化情報隠蔽、データ隠蔽の違いがよくわからくなったので、手持ちの本で調べてみた。

基準

基準としては、

  1. カプセル化情報隠蔽、データ隠蔽の関係
  2. カプセル化は隠蔽を含んでいるかどうか
  3. 対象はクラスのみか、そうでないか

などなど。
一番目はそのまんま。二番目は、

// 隠蔽せずともカプセル化か
class Hoge {
    int hoge;
    // なんかhogeを使うメソッド
}
// 隠蔽しなければカプセル化ではないか
class Piyo {
    private int piyo;
    // なんかpiyoを使うメソッド
}

という点、三番目は、

// これをカプセル化とするかどうか
interface Hoge {
    void method();
}

class HogeImpl impelments {
   void method() { ... }
}

結論

「みんな自由に言葉を使ってるんだな」
カプセル化情報隠蔽、データ隠蔽の関係は、みんな同じとするものもあれば全部違うものとするもののあるし、中間もある。
カプセル化は隠蔽を含んでいるかどうかは、ほとんどが含んでいるとしているけど、含んでいないとするものもある。
対象はクラスだけとするものもあるけど、そうでないものもある。


てことで、結論らしい結論は出せないな。もうみんな好きに使えばいいと思うよ。
2 番目に関しては、多数派に乗っかってカプセル化は隠蔽も含む、としておいたほうが無難かも。


以下、カプセル化情報隠蔽、データ隠蔽の何れかが載っていた本の引用。約 50 冊分くらいあるので注意。

オブジェクト指向における再利用のためのデザインパターン

要求はオブジェクトに対してオペレーションを実行させる唯一の方法であり、また、オペレーションはオブジェクトの内部データを変更する唯一の方法である。これらの制約により、オブジェクトの内部状態はカプセル化されているという。すなわち、オブジェクトの内部状態には外から直接アクセスすることはできず、さらにその表現形態も外からは見えない仕組みになっている。

1.6 デザインパターンで設計問題を解く (P.24)

内部データと内部状態は (Java で言う) フィールドのことだろうけど、表現形態ってのはよくわからない。
外からは見えないってことは、中からは見えるんだろうけど・・・

カプセル化
オブジェクトの表現や実装を隠ぺいすること。オブジェクトの表現をそのオブジェクトの外部から直接的に見たりアクセスしたりすることはできない。オペレーションがオブジェクトの表現にアクセスしたり修正したりする唯一の方法である。
用語集 (P.384)

オブジェクトの表現や実装を隠蔽するってことは、フィールドの隠蔽だけではない、と解釈していいのかな。

デザインパターンとともに学ぶオブジェクト指向のこころ (Software patterns series)

本書中では、「要求文書中から名詞を見つけ、それをオブジェクトにする」という 1980 年代のアプローチには従っていません。このアプローチでは、カプセル化というものが「データ隠蔽」として、そしてオブジェクトというものが「データ、および、それに対するアクセスや操作のために用いられる振る舞いを備えた物体」として定義されてしまうのです。これは、オブジェクトの実装方法のみに焦点を当てた、窮屈で狭いものの見方です。

第 I 部 オブジェクト指向ソフトウェア開発入門 (P.1)

カプセル化は、しばしば単純なデータ隠蔽として解説されています。通常の場合、オブジェクトは内部データメンバを外部に公開しないのです (つまり、アクセス可能性を protected か private にするわけです)。
しかし、カプセル化はデータ隠蔽と同じものではありません。実は、カプセル化とはあらゆる種類の隠蔽を含んでいるのです。
先の例では、講師はどの学生が学部生であるか、また大学院生であるかを意識する必要がありませんでした。学生の型は、講師から見えないように隠されているのです (つまり、学生の「種類」がカプセル化されているわけです)。
・・・

用語 解説
カプセル化 (encapsulation) データ隠蔽として定義されることが多いものの、あらゆるもの (型、実装、設計等) の隠蔽を指していると捉えるべきです。
1.6 オブジェクト指向パラダイム (P.17-18)
用語 定義
カプセル化 あらゆる種類の隠蔽を指します。オブジェクトはそのデータをカプセル化します。抽象クラスはそこから派生された具象クラスをカプセル化します。
オブジェクト指向用語 (P.25)

カプセル化とは、「あらゆるものを隠蔽すること」であると考えるべきです。言い換えれば、データを隠蔽すること可能です。しかし、以下のものを隠蔽することもできるのです。

  • 実装
  • 派生クラス
  • 設計の詳細
  • 実体化の規則

・・・
型のカプセル化は、ポリモーフィズムを使用する抽象クラスとその派生クラス (またはインタフェースとその実装) によって生み出されます。
・・・
なお、GoFカプセル化について言及している場合、そのほとんどは型のカプセル化を意味します。

8.3 カプセル化:従来からの考え方と新たな考え方 (P.106-108)

あえて説明はいりませんね。引用部分だけで理解できるでしょう。

アジャイルソフトウェア開発の奥義

このデザインパターンは、Command という概念カプセル化することで、システムの論理的な内部構造とシステムに接続するデバイスの詳細を切り離すことができたのだ。

13.1 シンプルな Command パターン (P.199)

JavaC++ でクラス間の結合 (カップリング) がカプセル化の境界線で取り扱われていたように、パッケージ間の結合は UML のエクスポートを示す表記を使って取り扱うことができる。

22.4 結合とカプセル化 (P.361)

第2版ではP.355


概念をカプセル化、と言っていることから、オブジェクト指向のこころと同じような使い方をしているのかな。

オブジェクト指向プログラミング入門

カプセル化 (encapsulation)
ある構造の中に情報を隠すテクニック、たとえばクラスの中にインスタンスデータを隠す手法を指す。
情報隠蔽 (information hiding)
ソフトウェア部品 (クラスなど) の利用者が、その部品をどう初期化してアクセスしたらよいかだけを知っていて、細かい実装については知る必要がないという原則。ソフトウェアシステムの構成要素間の相互接続を減らすでの、情報隠蔽は高信頼ソフトウェアの開発に役立つ。
データ隠蔽 (data hiding)
特定のサービスを提供するためにオブジェクトにどんなデータ値が収められているか、という実装上の細部を抽象化するためのカプセル化手法。
用語集 (P.508, )

減らすでの・・・
誤字は置いとくとして、データ隠蔽をカプセルの一手法と位置付けているのはオブジェクト指向のこころと同じ。
ただ、情報隠蔽にも言及していて、カプセル化をテクニック、情報隠蔽を原則としている。
つまり、情報隠蔽という原則があって、それを実現するためにカプセル化があって、さらに実装上の細部を抽象化するためにデータ隠蔽がある、という階層をなしている。

ドメイン駆動 (Programmer’s SELECTION)

ステートパターンの考え方は、個々のステートをひとつのクラス (ConcreteClassA、ConcreteClassB など) としてカプセル化するというものだ。

サンプル:ステートパターン (P.51)

仕様パターンは、同じようにクエリーのために使えるが、クエリーオブジェクトが汎用的なオブジェクトを使ってひとつずつ検索基準を設定していくのに対し、オブジェクトはドメインの知識をカプセル化し、意図を伝えるというコンセプトで使われる。
・・・
この場合、検索基準は外からはわからない。内容がよくわかるような名前のつけられたクラスが基準をカプセル化するのである。

ドメインパターン (P.63)

ステートをクラスとしてカプセル化する、ドメインの知識をカプセル化する、と言っていることから、オブジェクト指向のこころに近い感じ。
内容がよくわかるような名前のつけられたクラスが検索基準をカプセル化する、というのはなかなかいいな。処理を名前でカプセル化する、ってところか。

Exceptional C++ Style―40のクイズ形式によるプログラム問題と解法=スタイル編 (C++ in‐Depth Series)

『Webster's Third New International Dicrionary』によると、

en-cap-su-late vt
to surround, encase, or protect in or as if in a capsul
カプセル化 他動詞
囲む、包む、あるいは、カプセルで (カプセルに入れたかのように) 保護する。

プログラミングにおけるカプセル化も全く同じ意味を持つ。クラスの内部実装を保護するために、インターフェースで包んで隠蔽するわけだ。外部からはインターフェースしか見えない。
・・・


カプセル化は、オブジェクト指向プログラミングの最重要概念である。以上。


その他のオブジェクト指向テクニック (例:データ隠蔽、継承、およびポリモルフィズム) は、カプセル化の特殊な場合を提供するという意味から重要である。たとえば、

  • カプセル化はほとんど常にデータ隠蔽を意味する。
  • 仮想関数による実行時ポリモルフィズムは、基本クラスによって提供されるインターフェースを、(コードが書かれた時点では存在する必要さえない) 派生クラスによって提供される実装から完全に分離する。
  • テンプレートによるコンパイル時ポリモルフィズムは、インターフェースを実装から完全に分離する。必要な操作を持つクラスは、継承やその他の関係がなくても自由に交換して利用できる。

カプセル化が常にデータ隠蔽を意味するわけではないが、データ隠蔽は常にカプセル化の一種である。
カプセル化が常にポリモルフィズムを意味するわけではないが、ポリモルフィズムは常にカプセル化の一種である。

17. カプセル化 (P.120-122)

これもオブジェクト指向のこころとほとんど同じですね。

Modern C++ Design―ジェネリック・プログラミングおよびデザイン・パターンを利用するための究極のテンプレート活用術 (C++ In‐Depth Series)

汎用のファンクタは, 処理要求をオブジェクトとしてカプセル化するような設計を行う場合, 特に有効なものとなります。要求のカプセル化を行ったり, それに伴う汎用のファンクタを実現するものとして, Command デザイン・パターンというものがあります (Gamma 他 1995)。
簡単に言えば, 汎用のファンクタとは C++で許されている任意の処理起動を, 型の安全性を持ったファースト・クラス・オブジェクトとしてカプセル化したものです。より詳しい定義に従えば, 汎用のファンクタは:

  • 引数の一部または全てとして, 単純な関数へのポインタ, メンバ関数へのポインタ, ファンクタ, その他の汎用のファンクタといったものを受け付けます。これによって, 任意の処理の起動がカプセル化できます。
第 5 章 汎用のファンクタ (P.105)

これも何でもカプセル化ですね。

パターン指向リファクタリング入門~ソフトウエア設計を改善する27の作法

内部クラスのカプセル化
Javajava.util.Collections クラスは、Creation Method でクラスをカプセル化するとはどういうことかを示すよい例である。

Factory によるクラス群の隠蔽 (P.89)

Builder には複数の Composite[DP] がカプセル化されていることが多い。これら Composite オブジェクトの構築は、何度も出現したり、複雑であったり、エラーを起こしやすかったりすることが多いからである。
・・・
Composite を Builder でカプセル化するもう 1 つの動機は、クライアントコードと Composite コードとを切り離すことである。

Builder による Composite のカプセル化 (P.101)

これも何でもカプセル化と呼んでいるようですね。

プログラムデザインのためのパターン言語―Pattern Languages of Program Design選集

マネージャ (Manager) デザインパターンは、あるクラスのインスタンスの管理を、別個のマネージャオブジェクトの中にカプセル化する。

Chapter1 マネージャ (P.23)

これらのソケットラッパは、ソケットインタフェースのSOCKストリームのセマンテックス (semantics) を、移植可能 (portable) かつ型安全 (type-secure) なオブジェクト指向インタフェースの中にカプセル化する。

Chapter7 反応体:同期型イベント用の多重化分離及びディスパッチングハンドルのためのオブジェクト振る舞いパターン (P.131)

サービスハンドラは、ソケットのような入出力ハンドル (I/O handle) をカプセル化 (encapsulate) するデータモードトランスポート端点 (data-mode transport endpoint) を与える。

Chapter10 受付人―接続人:通信サービスの接続と初期化のためのオブジェクト振る舞いパターン (p.194)

変化するコードを安定なコードから分離する。理想的には、変化するコードは可能であれば必ずオブジェクトにカプセル化するべきだ。オブジェクトは個別のメソッドよりも再利用しやすいからだ。コードがカプセル化されれば、サブクラスを作ってメソッドを書かなくても、所望のオブジェクトの合成でバリエーションを作れる。

Chapter19 フレームワークの進化のためのパターン (P.454)

Gang-of-Four デザインパターンの多くは様々な種類の変更をカプセル化する。表19-1は、フレームワークの異なる場所がアプリケーションによって変化するときに利用可能なデザインパターンを示す[Gamma+95]。

変化するもの デザインパターン
アルゴリズム 戦略 (Strategy) 、訪問子 (Visitor)
動作 命令子 (Command)
実装 ブリッジ (Bridge)
変化への反応 観察者 (Observer)
オブジェクト間の相互作用 仲介者 (Mediator)
オブジェクトの生成 ファクトリメソッド (Factory Method) 、抽象ファクトリ (Abstract Factory) 、原型 (Prototype)
構造の生成 構築器 (Builder)
巡回アルゴリズム 反復子 (Iterator)
オブジェクトインタフェース アダプタ (Adapter)
オブジェクトの振る舞い 装飾器 (Decorator) 、状態 (State)

表19-1 フレームワーク変化に対して推奨するデザインパターン

同上 (P.454-455)

コンポーネントライブラリ中で、独立に変化するであろう複数の振る舞いをカプセル化しているクラスがあったら、それらを片っ端から、それぞれの振る舞いをカプセル化するクラスに分割する。

同上 (P.457)

これまたいろいろなものをカプセル化しており、オブジェクト指向のこころと同じような扱いのようだ。

ThoughtWorksアンソロジー ―アジャイルとオブジェクト指向によるソフトウェアイノベーション

カプセル化とは「データ、実装、クラス、設計、実体化の隠蔽」であると理解することと、カプセル化を適切に実現するコードを設計することは、まったく別のことなのです。

5章 オブジェクト指向エクササイズ (P.67-68)

これまたおぶ(ry

Javaセキュリティ

オブジェクト指向設計の大きな特徴の1つは、データの隠蔽とデータのカプセル化を行えることです。カプセル化によってオブジェクトは、そのデータ要素が直接的に操作されるのではなく、オブジェクトが提供するインタフェースを介してのみ操作されることが保証されます。

2.1 言語のセキュリティ構造 (P.200)

プロテクションドメイン:特定のコードソースとそのコードソースに許可されるパーミッションカプセル化したもの

5章 アクセスコントローラ (P..99)

データの隠蔽とデータのカプセル化がどう違うのかよくわからん。
ただ、パーミッションカプセル化、と言っていることから、データ以外もカプセル化の対象としているようだ。

詳説 正規表現 第3版

.NET では、Regex オブジェクトをアセンブリとしてカプセル化することができる。

9.6.1 正規表現アセンブリ (P.421)

.NET では、Regex オブジェクトをアセンブリにカプセル化することができる。

9.6.1 正規表現アセンブリ (P.428)

上が第 2 版、下が第 3 版・・・って、ここは全然変わってないな。
これだけで判断するのは難しいけど、フィールドの隠蔽がカプセル化とはしていないことはわかる。

オブジェクト指向入門 第2版 原則・コンセプト (IT Architect’Archive クラシックモダン・コンピューティング)

特定の特性を顧客から呼び出せないようにするメカニズムを情報隠蔽と呼ぶ。

2.2.7 情報隠蔽 (information hiding) (P.32)

情報隠蔽はフィールドの隠蔽?

情報隠蔽が意味するのはそういうことではなく、スプレッドシートプログラムを書く人がその実装で二分木が使われていることを知っていたとしても、その実装でなければ正しく機能しないような顧客モジュールを書くことができてはならないということだ。例えば、テーブルの実装がハッシュ法などの何かほかのものに変更された場合に動かなくなってしまうような顧客モジュールを書くことができてはならない。
前に述べた誤解の原因は、1 つには「情報隠蔽」という言葉そのものが物理的な保護を示唆することにある。「カプセル化 (encapsulation)」は情報隠蔽の同義語として使われることがあるが、おそらく、この言葉の方が言葉として適切である。

3.2.5 情報隠蔽 (P.66-67)

情報隠蔽は実装の隠蔽?どっちだよw
ただ、情報隠蔽カプセル化は同義語としている。
また、使う側が実装の詳細を知っているかどうかは関係ないというのは面白い見方だな。

カプセル化 [Encapsulation]
情報隠蔽を見よ。
情報隠蔽 [Information hiding]
あるクラスの性質の一部を顧客からアクセスできないようにする能力。アクセスの制限は明快な (特性の) エクスポートのポリシーと、ショート形式を主要なクラス文書として信頼することによって実現される。
オブジェクト技術用語集 (P.850, 853)

方法論・実践なら P.706, 709


情報隠蔽は能力・・・?よくわからん。

オブジェクト指向入門 第2版 方法論・実践 (IT Architects’Archive CLASSIC MODER)

表明を使えば参照の操作を正しく維持するのに役立つ (プロシージャ put と不変表明を参照) が、この種の操作が全くもって困難であること自体、オブジェクト指向で推進されているように、再利用可能なモジュールとしてカプセル化し、二度と同じ問題で困らないようにすべきであると強く主張する根拠である。

23.4.3 カプセル化と表明 (P.152)

カプセル化をサポートしている。すなわちオブジェクト内部のプロパティを隠し、公式のインタフェースを通じてアクセス可能にする。

31.6.3 境界モデル (P.498)
次にカプセル化レベル
このレベルの言語は、モジュールパッケージと呼ばれる構文的な単位で、一組のルーチンとデータ宣言をグループ化する方法を提供する。
34.1 言語による支援のレベル (P.558)

上の本の下巻。
下巻だけを読むと、上巻はいったいなんだったの?ってくらいカプセル化イコールフィールドの隠蔽に読める。

やさしいC++ 第3版 [やさしいシリーズ]

クラスの中にデータ (データメンバ) と機能 (メンバ関数) をひとまとめにし、保護したいメンバに private をつけて勝手にアクセスできなくする機能を カプセル化 (encapsulation) といいます。
・・・
カプセル化は、クラスがもつ重要な機能のひとつです。


重要 データと機能をひとまとめにし、メンバを保護する機能をカプセル化という。

カプセル化のしくみを知る (377)

カプセル化はフィールドの隠蔽のことってことですね。
カプセル化を「機能」としてるところは、「能力」としたオブジェクト指向入門と似たところがあるかもしれない。

詳説C++ 第2版 (C MAGAZINE)

重要な情報は非公開部に隠されます。このような手法を, 情報隠蔽 (information hiding) と呼びます。そして, 非公開部分をカプセルで覆うように公開部が存在し, 公開部には厳選された適正な処理のみが用意されます。利用者は, 公開された処理をインタフェイスとして操作します。このような手法を, カプセル化 (encapsulation) と呼びます。

情報隠蔽とカプセル化 (P.84-85)
情報隠蔽
情報は非公開部に隠される
カプセル化
非公開部は公開部の殻に覆われ, 利用者からは見えない。利用者側は公開部のメンバ関数をこのクラスのインタフェイスとして利用する
※抽象データ型
情報隠蔽カプセル化により, 利用者は型の具体的な構造を知る必要がなくなり, 型はインタフェイスのみにより決定される抽象的なものとなる
情報隠蔽とカプセル化 (P.84)

カプセルの殻が公開部、中身が非公開部とする考え方。
情報隠蔽をフィールドを非公開にすること (アクセスできる手段はなくてもいい)、カプセル化情報隠蔽を施した上で公開された処理を用意することをカプセル化としている。
これは他に類を見ない考え方かもしれない。

Javaアプリケーション作成講座―Swingプログラミング徹底攻略

カプセル化はプログラムの可視性を制御する機能で、プログラムへのアクセスを規制します。外部に公開する必要性のないコードは外部からアクセスできないように設定することで、複雑な内部事情を隠蔽します。これによって、予期しない不正なアクセスを防ぎ、プログラムの安全性を向上させることができます。また、プログラムの利用者にとっても、関係のない機能が隠蔽されることによって複雑なシステムが単純化されるため、利用が容易になります。

1.4.1 オブジェクト指向と言語 (P.15)

カプセル化を可視性の制御する機能としている。「複雑な内部事情を隠蔽します」とあることから、フィールドだけの隠蔽ではなく、メソッドも含んでいるっぽい。

それほど間違ってないプログラマ用語辞典

クラス内のフィールドや内部処理をしているメソッドなどを、外部からアクセスできないようにすること。


ドキュメントやコメントに懇切丁寧にそのモジュールの正しい使用方法を載せておいても、そこに final でないフィールドがあれば値を書き換え、そこに private でない関数があれば勝手にアクセスしてしまうという風習を持っている
プログラマたちの悪の手からモジュールを守る
ことを目標にしているような感じがするのは気のせいなのもの。

カプセル化 (P.51)

まぁ、プログラマ用語辞典はいいでしょう。
つか、Javaアプリケーション作成講座とほとんど同じだな。

たのしいRuby 第2版 Rubyではじめる気軽なプログラミング

データの操作はメッセージを通して行われます。オブジェクトの表現する情報が複雑になると、1 つのメッセージに対して必要となる操作は複雑になりますが、オブジェクトの利用者は実際にどのような手順で実際の操作が行われているかを知る必要はありません。このような隠蔽化をカプセル化といいます。

カプセル化 (情報の隠蔽) (P.141)

データの操作と制御の隠蔽をカプセル化としている感じ。シンプル。
また、カプセル化情報隠蔽 (情報の隠蔽) は同じものとして扱っている。

稼げるJava!今より楽するコーディング

オブジェクト指向では、クラスの属性 (プログラムでいう変数) への外部からの直接アクセスを禁止し、全てメソッド経由でアクセスさせることでクラスのモジュール性を高めることを「情報隠蔽 (information hiding)」又はカプセル化 (encapsulation) と呼ぶ。

あなたのクラスは秘密主義者?

たのしい Ruby と同じ考え方かな。

C++ Coding Standards―101のルール、ガイドライン、ベストプラクティス (C++ in‐depth series)

情報隠蔽は、プロジェクトのコスト、スケジュール、リスク等を次の 2 つの点で改善する。

  • 変更を局所的にする。情報隠蔽は変更による波及効果の範囲を狭め、結果的にコストを抑える。
  • 不変性を向上させる。プログラムの不変性を維持するコード (バグのあるときは不変性を壊してしまうコード) を限定する (項目 41 参照)。
11. 情報を隠蔽しよう (P.21)
例 1:適切なカプセル化
ほとんどのクラス (Matrix、File、Date、BankAccount、Security など) はメンバー変数を全て private にして持ち、適切なインターフェースを提供すべきである。
41. メンバー変数を private にする ただし、振る舞いのない集成体 (C スタイルの struct) は除く (P.72)

これはカプセル化がフィールド隠蔽を指す、でいいな。

JavaScript 第5版

JavaC++ などの従来のオブジェクト指向言語に共通する特徴として、クラスのプロパティをプライベートとして宣言できる点があります。プライベートとして宣言することで、そのプロパティはクラスのメソッドからのみアクセス可能となり、そのほかのコードからは操作できなくなります。データカプセル化と呼ばれる一般的なプログラミングテクニックでは、プロパティをプライベートにしておき、特別なアクセッサー (accessor) メソッドからしかアクセスできないようにします。

9.3.7 プライベートメンバ (P.165)

フィールドの隠蔽がカプセル化派ですね。
しかも、アクセッサー (getter/setter) 必須論者っぽい。

Java魂―プログラミングを極める匠の技

カプセル化は、クラスのインタフェースのみをクラスのユーザに公開するものであり、クラスの実装の詳細を明らかにするものではありません。


ユーザが setCoordinate() メソッドを呼び出す際に渡される Point オブジェクトは格納の前に必ずコピーされるので、このデータオブジェクトクラスは安全にカプセル化されています。同様に、coordinate が getCoordinate() メソッドから返された場合にも必ずコピーされます。開発者は内部オブジェクトへの参照を得ることができないので、絶対にカプセル化を壊すことはありません。

3.1.3 見せかけの不変な型 (P.82)

クラスの実装を〜と言っているのに、getter/setter レベルでしか話をしていない・・・
前半と後半で意見が変わっているとも読める、なんとも中途半端な感じ。

java.util パッケージのインタフェースは、他に選択肢がない場合を除いては、クラスのユーザに公開すべき唯一のコンポーネントです。これはカプセル化の考え方に従っています。カプセル化とは、プログラマがクラスのユーザに実装の詳細を公開しないで、クラスのインタフェースだけを公開することです。例えば、以下のコードは適切なインタフェースベース手法の例です。

public class SomeClass {
  HashSet someSet = new HashSet();
  
  protected Set someMethod() {
    return this.someSet;
  }
}
4.1.1 インタフェースベースの手法 (P.88)

ええええ、内部状態が露出してる!フィールドも非 private だ!!!
カプセル化とは、実装の詳細を公開しないことで、インタフェースだけ公開すること?またさっきと言ってることが変わってるよ・・・

オブジェクト指向エンジニアリングはカプセル化の概念に基づいています。つまり、オブジェクトの内部については、クラスのユーザからは見えないようにすべきです。ビットフィールドは、オプションの内部実装をユーザに公開するため、不適切なカプセル化の一例です。

7.3.3 不適切なカプセル化 (P.167)

また意見を変えたなこのやろう。この本は駄目な本なので気にしないことにする。

Effective Java 第2版 (The Java Series)

上手く設計されたモジュールは、その実装の詳細をすべて隠蔽し、実装と API をはっきりと分離しています。そして、モジュールは API を通してのみ他のモジュールと通信し、各モジュールはお互いの内部の動きについては知りません。この概念は、情報隠蔽 (information hiding) あるいはカプセル化 (encapsulation) と呼ばれ、ソフトウェア設計の基本的な教義の1つです [Parnas72]。

項目 13 クラスとメンバーへのアクセス可能性を最小限にする (P.67)

良いプログラムは、情報隠蔽 (information hiding) の原則を具体化しています。つまり、可能なところでは個々のモジュール内に設計上の決定を局小化*1していますので、個々の決定はシステムの残りの部分に影響を与えることなく変更できます (項目 13)。

項目 55 注意して最適化する (P.227)

情報隠蔽, → カプセル化

索引 (P.321)

情報隠蔽カプセル化を同じものとしている。
で、実装の詳細を隠蔽して、実装と API を分離、API のみを使用する、と。
フィールドの隠蔽だけを指しているとも、インターフェイスの裏に実装クラスを隠蔽することを指しているともとれるな。

Jakarta Commonsクックブック ―Javaプロジェクト必須のレシピ集

Transformer は変換ロジックを分離し、カプセル化します。ドメインモデル間で、あるいはオブジェクトタイプ間で変換が必要な場合は、その変換ロジックを Transformer 内にカプセル化すべきです。

レシピ4.10 オブジェクトの変換 (P.127)

変換ロジックをカプセル化と言っていることから、フィールドの隠蔽だけを指しているわけではないことはわかる。

センス・オブ・プログラミング! 抽象的に考えること・データ構造を理解すること

オブジェクト指向では、データをオブジェクト内に隠蔽し、限定された手続きのみで操作できるようにします。これをカプセル化と呼びます(図 4-2)。

データ構造とオブジェクト指向 (P.150)

フィールドの隠蔽のみを指しているよう。

プログラミング言語 Ruby

メソッド呼び出しでかっこが省略されているので、これらのコードはまるでオブジェクトの名前付きフィールドか名前付き変数の参照のように見える。これは意図的なものだが、実際には Ruby はオブジェクトのカプセル化については厳格な言語だ。オブジェクトの外からオブジェクトの内部状態にアクセスすることはできない。

1.1.1 Ruby はオブジェクト指向言語 (P.3)

Ruby のオブジェクトは、厳重にカプセル化されている。オブジェクトの状態には、オブジェクトが定義するメソッドを通じてでなければアクセスできない。
・・・
オブジェクトの状態がこのように厳重にカプセル化されているのとは裏腹に、Ruby のクラスは非常にオープンである。

7章 クラスとモジュール (P.222)

これまたフィールドの隠蔽のみを指しているよう。

プログラミング作法

実装の詳細を隠蔽しよう。インターフェイスの裏にある実装は、プログラムのほかの部分に一切影響や支障を及ぼすことなく変更できるように隠しておく必要がある。この種の構成上の原則を表現する用語は何種類かあり、情報隠蔽カプセル化、抽象化、モジュール化などといった用語はどれも同じ種類の発想を表している。

4.5 インターフェイスの原則 (P.148)

インターフェイスを例えば Java の interface と取るか、例えば C++ のヘッダのようなもと取るかによって、ちょっと意味が変わってきそう。
ただ、情報隠蔽カプセル化は同じものとしている。

Javaプログラマのためのアルゴリズムとデータ構造

このように, データとそのデータに対する操作手続きを組みにすることをカプセル化 (encapsulation) といいます。カプセル化を行うことによって, 用意された操作を利用しなければ, データを参照・変更することができなくなります。

3.1 抽象データ型 (P.32)

これはフィールドの隠蔽を言ってますね。

はじめて学ぶUML―オブジェクト指向の基礎からUMLの利用法まで、しっかりよくわかる!

カプセル化を簡単に言うと「公開部分と非公開部分に分けること」です。そのため、情報隠蔽と呼ばれることもあります。

カプセル化 (P.34)

これはクラスの中の話だと思うんで、フィールドの隠蔽がカプセル化ってことですね。
さらに、カプセル化情報隠蔽は同じ、と。

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

「委譲の隠蔽 (157)」の動機では、委譲オブジェクトの利用をカプセル化することの有効性について述べました。

第7章 オブジェクト間での特性の移動 (P.160)

オブジェクト指向の主要な教義の1つは、カプセル化、あるいはデータの隠蔽です。すなわち、自分のデータを公開してはならないということです。

第8章 データの再編成 (P.206)

ちょっと判断に困るなぁ。

Java言語で学ぶリファクタリング入門

適切に情報を隠すことを一般に情報隠蔽 (information hiding) といいます。情報隠蔽は極めて重要です。

第0章 リファクタリングとは (P.10)

フィールドを private にして外部からの直接アクセスを禁じ、必ず getter メソッドを使ってフィールドにアクセスさせることをカプセル化 (encapsulation) といいます。

第6章 クラスの抽出 (P.125)

クラス同士の関係をシンプルにするためには、情報隠蔽がどうしても必要になります。
・・・
委譲クラスへアクセスするためのメソッド (委譲メソッド) をサーバクラスが提供してやれば、クライアントクラスは委譲クラスを利用しなくてもよくなります。これで、サーバクラスが委譲クラスへ委譲しているという実装詳細を、クライアントクラスから隠すことができます。

第14章 委譲の隠蔽 (P.310)

これはリファクタリングを元に書かれているので、参考までに。ただ、getter を使ってフィールドにアクセスさせることをカプセル化と呼ぶのはちょっと違うんじゃ。

オブジェクト脳のつくり方―Java・UML・EJBをマスターするための究極の基礎講座

カプセル化とは、

カプセル化

  • クラスに仕事を割り振るときに、仕事の具体的なやり方はその仕事の責任をもった担当 (クラス) だけが知っているようにして、その担当に仕事を頼む人は、その中身をしらないようにしなさい

ということです。
風邪薬の錠剤は、よくカプセルになっています。そのカプセルの中にはいろいろな種類の薬が入っていますが、我々はその中にどんな種類の薬が入っているかは全然理解してません。しかし、カプセルに入った風邪薬を飲むと「風邪が治まる」ということだけは知っています。こんな感じのイメージがカプセル化というわけです。

2.8 適当解説:カプセル化 (P.21-22)

これもフィールドの隠蔽のことでいいのかな。
委譲を含めてると考えてもいいかも。
カプセルを使った説明は良くあるけど、そのどれとも違う感じの説明になってるのが面白い。でも、これはわかりにくいと思うんだけど・・・

プログラマの完全常識 開発者が知っておくべきプロの知恵

カプセル化」は, データとメソッド (データに対する処理) をまとめることです。クラスというカプセルの中に, データとメソッドをまとめて記述します。

知識 2-13 Java のオブジェクト指向プログラミングに関する言語構文 (P.107)

カプセルの殻がクラス、中身がデータとメソッド。で、隠蔽はなくてもいい、と。斬新ですね。
このページはこの本を参考にしたと思われる。

プログラミングのセオリー

カプセル化という言葉から「ブラックボックス化」をイメージする人が多いようです。そのため、カプセル化の例として、フィールドに private 属性を指定し、それを読み書きする public なメソッドを用意するというサンプルプログラムがよく示されます。このようなプログラムのメリットは、フィールドに書き込まれる値をチェックし、不適切な値が代入されないようにできることです。
・・・
このような例を見ていると、「フィールドは絶対に private にしなければいけない」と思い込んでしまうでしょう。しかし、それではコードが長くなってしまいます。もしも、フィールドが 10 個あるクラスなら、それらを読み書きするメソッドは 20 個必要になります。
カプセル化に対するイメージを変えましょう。「ブラックボックス化」ではなく、「データと処理を一体化する (1 つのクラスにまとめて記述する) ことがカプセル化である」または「そもそもオブジェクトは振る舞いと属性を持つものである」というイメージに変えましょう。
つまり、フィールドとメソッドを持つクラスを記述するだけで、すでにカプセル化が行われているのです。JavaC# では、クラスに属さないデータ (C 言語のグローバル変数に相当するもの) を定義できないので、自然とカプセル化ができるはずです。フィールドに private を指定することにこだわる必要はありません。

カプセル化のイメージを考え直す (P.270)

うーん、見事に getter/setter 絶対必要派ですね。
それだけじゃなくて、クラスの中に置けばカプセル化とな。

OOP 言語を使えば、継承、カプセル化多態性を自然と実践できる

オブジェクト指向の考え方とテクニックを区別する (P.267)

なんて書いてるwww
OOPL を使ったところで出来上がったプログラムがオブジェクト指向かというと、それは違うってのは誰もが認めるところなのに、矢沢さんはそうは考えてないみたいです。自分が OOP を理解できてないから、考えたくないとか?

オブジェクト開発の神髄?UML 2.0を使ったアジャイルモデル駆動開発のすべて

クラスが何を知っていて何を行うかを「決める」ことを、クラスを「抽象化する」と言います。クラスがこれらの事柄をどう達成するか設計すると言うのではなく、クラスを「カプセル化する」といいます。情報に対するアクセスを制限してうまくクラスを設計することを、情報を「隠蔽する」と言います。
・・・
システムとして動くために必要なシステムの機能をどのようにモジュール化するかという問題は、カプセル化によって対処します。オブジェクト指向の世界では、システムはクラスにモジュール化され、クラスはさらにメソッドと属性にモジュール化されます。これを、振る舞いをクラスにカプセル化する、あるいは、機能をメソッドにカプセル化すると言います。
カプセル化は、設計時に考慮すべきことであり、システム内で機能をどのように区分けするかという視点でクラスを捉えることです。システムを構成する部品は内部がどう実装されているかを知らなくても使えるようになっているべきです。

2.6 抽象化、カプセル化、情報隠蔽 (P.55-56)

抽象化はクラスが何を知っているかが必要、というのは斬新かも。
何を行うかを決めることを抽象化と呼ぶ、ってのはよくあるけど、それプラス何を知っているかも必要、とな。
で、どう達成するかを決めることをカプセル化すると言う・・・?
さらに情報に対するアクセスを制御してうまくクラスを設計することを情報隠蔽と言う・・・?
なんかわけわからん。


カプセル化は設計時に考慮すべきこと、ってのは考えたことなかったな。
てことは、単純なフィールドの隠蔽を指しているわけではなさそう。

カプセル化
関連する概念を、クラスやコンポーネントといった 1 つの項目にグループ化すること。
情報隠蔽
属性に対する外部からのアクセスを制限すること。
用語集 (P.518, 527)

カプセル化で隠蔽についてはなにも規定していないところを見ると、カプセル化情報隠蔽は全く別物であるとしているのかな。
カプセル化だけなら隠蔽されている必要はないし、情報隠蔽だけなら関連する概念はまとまってなくていい、と。

ソースコードリーディングから学ぶ Javaの設計と実装

情報隠蔽とは、あるクラスの実装の詳細が他のクラスから隠蔽される形で、プログラム分割を行うという設計原理です注 2
・・・
注 2 類似の概念に「カプセル化」がありますが、厳密には両者は異なる概念です。データと振る舞いとを 1 つにまとめることを意味するカプセル化は、情報隠蔽の設計原理を実現する手段の 1 つにすぎません。

10.1 オブジェクト指向ソースコードの特徴 (P.209)

これは新しい。情報隠蔽は実装の詳細を隠蔽して、分割を行う設計原理、カプセル化はデータと振る舞いとをまとめる情報隠蔽実現の手段の 1 つ、と。
これの逆はいくつか本があるんだけども・・・?


それと、「Java の」設計と実装を学ぶわけじゃないから注意が必要。あくまで、Java で書かれたライブラリ等の設計と実装を学ぶ本。

More Exceptional C++ さらに40のクイズ形式によるプログラム問題と解法 (C++ In‐Depth Series)

標準 C++ [C++98] の 17.1.18 に traits クラスの記述がある。

インスタンス化された型のオブジェクトを操作するために、テンプレートクラスとテンプレート関数のセットをカプセル化するクラスである※2

・・・
※2 ここで言う「カプセル化」とは、殻の中に隠蔽することではなく、ひとまとめにするという意味で使っている。 traits クラスの中身を全て公開するのはよくあることで、実際、struct を使ったテンプレートとして実装されることが多い。

項目 4:拡張可能なテンプレート:継承と特性 (traits) (P.20)

カプセル化には複数の意味がある、と言うことですね。

データベースシステム概論

唯一の条件は, スカラ値の内部構造は DBMS に対して "見えない" ようにしなければならないことである―すなわち, 4 章で説明したよう, DBMS から見る限り, 値はスカラ (すなわち "原子的") である. わけのわからない言葉を使うためには, 値は "カプセル化 (encapsulation)" されていなければならない.

19.2 定義域 (P.596)

すべてのオブジェクトはカプセル化 (encapsulation) されている. この意味するところは, 与えられたオブジェクト, 例えば DEPT の内部表現―すなわちその内部構造―は, そのオブジェクトのユーザには見えないということである. その代わり, ユーザはそのオブジェクトがある機能 (「メソッド」) を実行できるということだけを知っている.
・・・
カプセル化のアイディアに従って, オブジェクトは, やや大まかだが「私用メモリ (private memory)」と「公用インタフェース (public interface)」をもつものと記述されることがある.

22.3 オブジェクト, メソッドおよびメッセージ (P.691)

しかし, カプセル化の概念があまりにも遠大すぎて, 実現できないかもしれないということに注意されたい. データベースが最初に創成されたときには予見できなかった方法でデータをアクセスする要求は常にあるだろうが, 新しいデータアクセスの要求が起こるたびに, 新しい手続きコードを書かなければならないという考えは単純に受け入れられない. 全く, そんなことは関係型以前のシステムの状況に他ならないし, それは, データベース・システムの堕落に一役かうだけだ.
そのため, システムは, カプセル化されないが, どこからでも見えるように「インスタンス変数」を公開するような「オブジェクト」のサポートを付け加えるべきだと思う. そして―少し先走るが―このようなカプセル化されない「オブジェクト」は, まさしく関係におけるタプルなのである (25.3 節参照). 少なくとも原理的にはカプセル化されない関係は, カプセル化されたオブジェクトと同じくらいデータの独立性を提供することができる (上で説明されるように) ということに注意されたい. さらに原理的には, 型の階層, 継承などの概念は, 少なくともカプセル化されたオブジェクトと同じくらいうまくいく, カプセル化されない関係にも適用されることにも注意されたい (19 章で説明されるように). そして, もちろん, 当該の関係に対する特有なメソッドによってアクセスされる代わりに, よく知られた, 組み込み型の, 関係代数の包括的な集合演算によって関係がアクセスされ, これによって「思いもよらなかった要求」の目的を満たすことができる.

25.2 「オブジェクト指向モデル」の概観 (P.755-756)

これは・・・
とりあえず、プログラムのことを言ってるんじゃなくて、RDB の話なので、あくまで参考程度にね。

Ship It! ソフトウェアプロジェクト 成功のための達人式ガイドブック

データアクセスのための API を定義すると、データの格納方法や取得方法がカプセル化されて、システムのほかのオブジェクトはその詳細を関知する必要がなくなります。

システムオブジェクトを定義する (P.113)

これは getter/setter のことを言っているのかな?これだけではなんとも判断ができないな・・・

プログラミングC#―C#2.0/.NET2.0/Visual Studio2005対応

クラスを記述することで、あるものの性質とそれができることを、単一で自己完結かつ自立したコードの塊カプセル化できます。これがクラスというものの大きな利点です。例えば、Windows リストボックスコントロールの内容を並べ替えたいときは、そのリストボックスに自身をソートするように指示すればよいのです。そのリストボックスがソートをどうやって行うかは問題ではありません。プログラマは、それがソート可能であるということだけを知っていればよいのです。カプセル化ポリモーフィズム、継承と並んで、オブジェクト指向プログラミングの 3 本柱の 1 つです。

4章 クラスとオブジェクト (P.67)

プロパティはメンバ変数のように見えるので、利用者にシンプルなインターフェイスを提供できます。また同時に、メソッドとして実装されることで、よいオブジェクト指向設計に必要なデータ隠蔽を行えます。
・・・
プロパティには、オブジェクト指向には欠かせないデータの隠蔽とカプセル化を犠牲にすることなく、利用者側では直接的にアクセスできるということと、開発者側では入力データを検証できるという 2 つの利点があります。

4.7 プロパティによるデータのカプセル化 (P.97〜100)

うーん、判断に困る。
データ隠蔽はフィールドの隠蔽のことを指しているようだけど、カプセル化は今までのどれとも違うような、所々似てるような・・・

Java並行処理プログラミング ―その「基盤」と「最新API」を究める―

上手に組織化されたメンテナンス性の良いクラスの集まりを作る、オブジェクト指向のテクニック―カプセル化やデータ隠蔽など―を使っていれば、その同じテクニックがスレッドセーフなクラス作りを支えてくれます。その問題の変数にアクセスするコードが少なければ少ないほど、すべてのコードが正しい同期化をしている状態を確立しやすくなり、変数がアクセスされる条件を判断するのも容易になります。Java 言語はステートのカプセル化プログラマに強制しません。
・・・
抽象化*1カプセル化と実行性能が両立しないときもあります。
・・・

*1
抽象化 (abstraction)、ステートを大きなクラスの裸のフィールドにするのではなく、特定のクラスとそのオブジェクトで表現し、必要なインタフェイスだけを public メソッドで提供する。例:1 を足すという操作だけ必要なら、一般的な add() メソッドは提供すべきでない。public メソッドは必要なら synchronized メソッドにする。カプセル化 (=オブジェクト化) とほぼ同意義だが、とくにデータや物理的で低レベルの機能を表すオブジェクトに関して使う。たとえばソケットは TCP/IP 通信機能の、高級で使いやすいオブジェクトへの抽象化だ。
第 2 章 スレッドセーフ (P.18-19)

オブジェクトの内部的なステート変数を公開するとカプセル化に違反し、不変項の保全が困難になります。

3-2 公開と逸出 (P.46)

ステートってのはステートパターンじゃなくて、フィールドの値のことですね。
てことはカプセル化とデータ隠蔽は同じもの、ってことかな。
ただ、抽象化とカプセル化とオブジェクト化 (インスタンス化とは多分別物。クラス化ってこと?) がほぼ同意義ってのはちょっと引っかかる。

C++プログラミングの処方箋―ひと味違うコードを書くための99の鉄則 (Programmer’s foundations)

Command パターンは処理をオブジェクトとしてカプセル化するため、オブジェクトを利用する利点を有効に活用できます。

鉄則 92 コード再利用のための public 継承

これだけでは判断できないけど、カプセル化がフィールドの隠蔽と同じじゃない、ってことはわかる。

Javaプログラミングの処方箋 (Programmer’s foundations)

オブジェクト指向の特徴の 1 つがカプセル化です。カプセル化によって、オブジェクトのフィールドへアクセスする際には所定の手続きを踏まなければならないようにすることができます。
・・・
カプセル化の大きな目的の 1 つは、不変式が破られないようにオブジェクトを守ることです。

鉄則 45 カプセル化

所定の手続きを踏めばオブジェクトのフィールドにアクセスできる・・・?

ソフトウェア工学―プロセス・開発方法論・UML (Information Science&Engineering)

このように抽象データ型に対して情報や操作を制限することを情報隠蔽と呼ぶ.
・・・
全ての抽象データ型をクラスとし, 情報隠蔽を行うことで, 先のようなプログラムの作成を禁止することが可能になる.

4.2.2 情報隠蔽

この本はいろいろと駄目な本なので参考程度に。

人月の神話―狼人間を撃つ銀の弾はない (Professional computing series (別巻3))

二番目の見方は、カプセル化を強調するものだ。これは、部品の内部構造は見ることもましてやデザインすることもできないことを意味する。

オブジェクト指向プログラミング―真鍮の弾丸は使えるのか? (P.207)

パルナスのモジュールに関する情報隠蔽の定義は、非常に重要な研究計画の第一発表段階にあたり、オブジェクト指向プログラミングの知的先祖なのだ。彼は、モジュールを独自のデータモデルおよび演算一式を備えたソフトウェア実体と定義した。データは適切な操作を介してのみアクセスできる。
・・・
だが実は、オブジェクト指向プログラミングで実現がもっとも期待されているのは、第一段階に由来するものだ。すなわち、モジュールのカプセル化 (隠蔽) と、それに加えて、再利用のためにデザインされたテスト済みの事前作成のモジュールライブラリまたはクラスに関するアイディアである。

情報隠蔽に関して、パルナスは正しく、私は誤っていた (P.264)

情報隠蔽カプセル化は同じものとしてるようだけど、その意味するところはちょっと読み取れない。

マルチパラダイムデザイン

クラスインタフェースの背後に実装の細部を隠蔽することは, オブジェクトパラダイムの触れ込み文句の 1 つである. しかしこのアイディアは, もちろん, オブジェクトと共に登場した新しい概念ではない. モジュール設計が謳い始められた頃に登場してきた原理である. エンドユーザはビジネスドメインのポリシーに対応する設計部分だけを操作できるのが望ましい. これが Parnas の説いた情報隠蔽の精神である.

1.9.1 ポリシーとメカニズム (P.27)

プログラミング言語の視点から見ると, オブジェクト指向プログラミングはモジュールプログラミング (カプセル化, encapsulation) + インスタンス化 (instantiation, 1 つのモジュールに対して複数のインスタンスを生成できる能力) + 継承とポリモーフィズムである.

5.1.3 仮想関数 (P.114)

private 継承のセマンティクスが IS-A ではなく HAS-A であるという理由から, ほとんどのプログラマ (特に純粋主義者) は, private 継承の代わりに, 明示的にカプセル化 (encapsulation) を使うことを好む (図 6.5).

6.7.1 2 つのドメインを整合させる (P.132)

委譲をカプセル化としていることから、カプセル化はフィールドの隠蔽だけを指すものじゃないとしているってことでいいのかな。

Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

カプセル化の利点は、ちょっと考える以上に重要です。データメンバをクラスのクライアントから隠して (つまり、カプセル化)、メンバ関数のみがそのデータにアクセスできるようにしておけば、常にクラスの不変な条件が成り立つようにしておけます。
・・・
public にするということは、カプセル化しないということです。
・・・
カプセル化の観点から言えば、事実上、2 つのアクセスレベルしかないのです。(カプセル化になる) private と (カプセル化にならない)「その他」です。

22 項 データメンバは private 宣言しよう (P.98-99)

何かがカプセル化されているということは、それが見えないところに隠されているということです。見えるものが少ないほど、いろいろな変更が可能になり、柔軟性が増します。変更の影響を受けるのは、その変更が見えるものだけだからです。つまり、カプセル化するほど、変更する能力が増すわけです。

23 項 メンバ関数より、メンバでも friend でもない関数を使おう (P.101)

フィールドの隠蔽がカプセル化を意味するってことですね。
ただ下で「何かが」という表現があるので、上はカプセル化の中で「データの」カプセル化を単にカプセル化と呼んでいる可能性は捨てきれない。

*1:局所化のことと思われる