アクセス制御と継承
アクセサ
オブジェクトの持つ状態にアクセスする必要がある場合、アクセス属性の設定によらず、アクセスしたい値を参照、変更するためのメソッドを用意する方法も考えられます。
図2-1は時刻を表すクラスTimeOfDayに時間を参照、変更するメンバ関数getHourとsetHourを追加した例です。メンバhourのアクセス属性はprivateなので、外部から直接アクセスはできませんが、このようなメンバ関数を使えば値にアクセスすることができます。
しかし、値の参照、変更のためだけにメソッドを定義するのは面倒なだと思うかもしれません。図2-2を見てください。時刻を分だけで保持する方式に変更しても、関数の定義だけ変更すればインタフェースを変えないですむことが分かります。
このように、オブジェクトの属性値にアクセスするためのメソッドをアクセサと呼び、値を参照するためのアクセサをゲッタ(getter)、値を変更するためのアクセサをセッタ(setter)と呼びます。ここで「属性値」という言葉を使いましたが、図2-2の例のように、アクセスする対象が必ずしもインスタンス変数であるとは限りません。そのような属性があるものとして扱えるという点が重要です。アクセサは通常は言語仕様ではなく、オブジェクト指向言語における書き方の習慣です。
JavaやObjective-Cでは、インスタンス変数のアクセス属性を指定することもできますが、アクセサを記述することが推奨されています。特にObjective-Cでは、アクセス制御の機能は実際のプログラミングでほとんど使われません。Smalltalkは外部からインスタンス変数に直接アクセスできませんので、インスタンス変数と同じ名前のアクセサを用意するという方法がよく使われます。
アクセサを仕様として取り入れた言語もあります。例えばRubyでは、インスタンス変数を指定して、アクセサを簡単に作る方法が用意されています。
プロパティ
アクセサに関連した、注目すべき機能を紹介します。
図2-3はC#の簡単なクラス定義とその利用例を示したものです。クラスFruitはインスタンス変数u_priceを持っていますが、アクセス属性がprivateなのでクラスの外部からはアクセスできません。代わりに、Priceという名前でプロパティを定義します。
プロパティは外部からアクセス可能なインスタンス変数であるかのように、値を参照したり、代入したりすることができます。参照する時にはgetに書かれた定義が、代入する時にはsetに書かれた定義が実行されます。setにあるvalueは代入される値を含む暗黙のパラメータです。利用する側からはpublic属性を持ったPriceというインスタンス変数があるのと変わらないという点に注目してください。プロパティにgetとsetを記述すると読み書きが可能になりますが、getだけ書くと読み出しのみ、setだけで書き込みのみのプロパティを定義できます。
Objective-C 2.0でも宣言プロパティという機能を導入して、アクセサの定義と呼び出しが簡単にできるようになりました。こちらの場合も、アクセサに対応するインスタンス変数が存在する必要はありません。
オブジェクト指向は言語やプログラミングだけではなく、要求分析や設計の段階から使われています。ソフトウエアの中でオブジェクトがどのような役割を担うかということをUMLなどの図を使って分析し、備えるべき操作と属性を早い段階から決めておく必要があります。
属性は従来、プログラミングの段階ではインスタンス変数かアクセサを使って実装されていましたが、プロパティを利用するとインタフェースをまったく変更せずにクラス内の実装だけを簡単に変更できます。大変有用な機能であると言えるでしょう。