http://martinfowler.com/bliki/AccessModifier.html

オブジェクト指向言語ではプログラムはクラスと呼ばれるモジュール群に分かれます。 それぞれのクラスは機能(features)をもっており、データ(フィールド)とメソッドで構成されます(すべての言語がこの用語を使うわけではありませんが、役割は一緒です)。 言語には、どのクラスがあるクラスの機能にアクセスできるのかについてのルールがあり、たいていクラスに適応されるアクセス修飾子に基づいて決まっています。

C++ の選択

おそらく最も影響力のあるアクセス修飾子はC++の3つから始まりました。

  • public: どのクラスもアクセスできる
  • protected: どのサブクラスもアクセスできる
  • private: 他のクラスはアクセスできない

他のクラスやメソッドに対して friend を使ってアクセスを許すこともできます。「C++ では友達同士はお互いのプライベートな部分を触ることができる」と言われる所以。

Java

JavaはC++を基にしています。パッケージについての表記が加えられました。これは振る舞いにも影響しました。

  • public: どのクラスも
  • (package): (デフォルト。アクセス修飾子を使わない)同じパッケージ内のクラス
  • protected: サブクラスと、同じパッケージ内のクラス
  • private: 他のクラスはアクセスできない

JavaのprotectedとC++のprotectedの微妙な違いに注意しましょう(混乱するだけでしょうが)。

C

C#もC++モデルを基にしています。

  • public: どのクラスも
  • internal: 同じアセンブリ内のクラス (デフォルトだが、明示することも可能)
  • protected: サブクラス
  • protected internal: サブクラスと、同じアセンブリ内のクラス
  • private: 他のクラスはアクセスできない

C#においてアセンブリとは集約の物理的な単位で、dll や jar、つまりバイナリに相当します。C#は論理的な単位(ネームスペース)も持っており、javaのパッケージに似ていますが、アクセス修飾子とは関係ありません。

Smalltalk

Smalltalkはよく純粋なオブジェクト指向言語だと言われます。C++、Java、C#以前のものです。Smalltalkはアクセスを制御するためのキーワードは用意されておらず、ひとつのやりかたしかありません。Smalltalkerたちは、フィールドはprivate、メソッドはpublic扱いだと言うでしょう。

しかしながらprivateなフィールドはC++系の言語のそれとは厳密には異なります。 C++などではアクセスはコード(textual)のスコープと考えられているのです。 PersonクラスのサブクラスであるProgrammerクラスを例にしましょう。 2つのインスタンス(MartinとKent)があります。 C++では、両方のインスタンスは同じクラスですから、MartinはKentのprivate部分へのアクセス権を持っています。 一方、Smalltalkの世界観では、アクセス権はオブジェクトに基づいています。 MarinとKentは別のオブジェクトですので、MartinはKentのフィールドとは無関係となります。 繰り返しますが、すべてがオブジェクトに基づいているため、たとえPersonクラスで宣言されていたとしても、 Martinは彼のすべてのフィールドに手が届くのです。 そのため、Smalltalkでのデータはprivateよりもprotectedに近いと言えます。 オブジェクトのスコープによって、それは場面によりけりですが。

アクセス制御はアクセスを制御するわけではない

privateなフィールドは他のどのクラスもアクセスできないということを意味する……’'’わけない!’'’ほとんどどの言語でも、アクセス制御の仕組みを壊すことは可能なのです。たいていは、リフレクションを使った方法を用います。なぜなら、デバッガやその他システムツールがprivateなデータをみる必要があるためです。そのため、たいていリフレクションインターフェイスによってそれが可能となります。

C++はこういったリフレクションを持っていません。しかし、C++は基本的にオープンメモリですので、直接メモリ操作を行うことによって可能となります。

アクセス制御の目的は、アクセスを防ぐことではなく、むしろクラスがあることを秘密にしておきたがっているという合図を送ることなのです。アクセス修飾子を使うということは、プログラミングにおける多くのことがそうであるように、本来はコミュニケーションに関するものなのです。

published メソッド

もうひとつのアクセス修飾子をいれる余地があると論じてきました。わたしは’'’published’'’と呼んでいます。 プロジェクトチーム内において他のクラスに公開する機能と、他のチームに公開する(APIのような)ものとは根本的に異なると思っています。 publishedな機能はpublicな機能のサブセットであり、異なるものとして扱われなければなりません。 publishedとpublicの違いは、publicとprivateの違いよりもずっと重要です。 これについてはIEEEソフトウェアのコラム(PDF)で詳しく論じています。