今まで作成したサンプルは、危険が潜んでいます。それは、スピードやガソリン残量を直接指定することができるという点です。急発進や、急停車、走行中にもかかわらず、ガソリン残量を変更できてしまいます。このままでは、完成されたオブジェクトとは言えません。
そこで、オブジェクト指向の特徴のひとつである「カプセル化」を使用して、安全なクラスを作成しましょう。クラスを定義する際に、アクセス修飾子を指定することにより、カプセル化を行うことができます。アクセス修飾子は以下のような指定ができます。
アクセス修飾子 | 意味 |
---|---|
public | クラスの内部・外部問わず、自由にアクセスすることができます。アクセス制限のレベルが最も低い修飾子です。 |
protected | クラスの内部と、派生したクラスからはアクセスすることができます。 |
internal | 同一プログラム内からであれば、自由にアクセスすることができます。 |
protected internal | protectedとinternalを合わせたアクセス修飾子です。 |
private | クラスの内部からしかアクセスすることができません。アクセス制限のレベルが最も高い修飾子です。 |
○ プロジェクト
プロジェクトを作成して確認してみましょう。
プロジェクトの種類 | コンソール アプリケーション |
---|---|
プロジェクト名 | CapsuleTest |
○ 作成の準備
「InstanceTest」プロジェクトを修正して作成しましょう。IntsantTestソリューションフォルダーのコピーを作り、フォルダー名をプロジェクト名に変更してください。コピーしてフォルダー名を変更したフォルダーからソリューションファイルを開いてVisual Studioを起動してください。起動するとプロジェクト名は変わっていませんが、複製を編集することになります。
○ プログラム
Carクラスのフィールドを外部から直接操作できないようにしましょう。次のようにプログラムを変更してください。
Car.cs
○ クラス図
○ 解説
12行目と15行目のフィールド変数のアクセス修飾子は「public」を指定していたため、外部のクラスから直接アクセスできました。今回は、カプセル化をするために一旦これらの行をコメントアウトしてプログラムから外しています。13行目と16行目でアクセス修飾子を「private」に変更することにより、外部のクラスからアクセスすることができなくなります。
すると、このクラスを利用する記述の部分で変化が生じます。フィールドに値を代入したり、参照したりする記述ができなくなります。そのため、必要であればメソッドとして値を代入したり、参照したりする機能を追加しなくてはなりません。
○ プログラム
次のようにCarクラスにメソッドを追加してください。
Car.cs
○ クラス図
○ 解説
Carクラスを利用するクラスからフィールド変数に代入することで初期化をしていましたが、カプセル化によりフィールド変数にアクセスできなくなったために、49~53行目ではフィールド変数を初期化する手続きを用意しました。引数にガソリン量を受け取り、スピード情報を「0km」に、ガソリン量を引数のデータで初期化しています。
また、Carクラスを利用するクラスからフィールド変数を直接参照してスピード情報やガソリン量を取得していましたが、カプセル化によりフィールド変数にアクセスできなくなったために、56~59行目ではスピードを戻り値として返す手続きを、62~65行目ではガソリン量を戻り値として返す手続きを用意しました。
○ プログラム
では、Carオブジェクトを生成して利用しているプログラムも修正しましょう。
Program.cs
○ 解説
14、17行目では、Carクラスのカプセル化によりフィールド変数にアクセスできなくなったためにエラーとなります。そのため、コメントアウトしています。その代わりに15、18行目で新たに手続きとして用意されたスピードやガソリン量を取得するメソッドを呼び出しています。
27、28行目では、Carクラスのカプセル化によりフィールド変数にアクセスできなくなったためにエラーとなります。そのため、コメントアウトしています。その代わりに29行目で新たに手続きとして用意された初期化を行なうメソッドを呼び出しています。
このようにカプセル化をすることにより、クラスの利用者側から直接データを参照・設定できなくすることにより、クラス作成者の意図に沿わない方法で使用されるのを避けることができます。手続きを用意することによって必要な処理をさせることができます。また、クラスを利用する側も特に意識することなく安全に、クラスを利用することができるようになります。
一般的に、フィールドはprivate指定で非公開にして、メソッドをpublicで公開にします。ただし、内部処理などで使うメソッドはprivateにして、外部から利用されないようにします。