【C#入門】カプセル化(プロパティ)について分かりやすいサンプルコードで徹底解説①
データの破壊や漏洩を防ぐというのは、オブジェクト志向の重要な目的の一つです。
そのためにはオブジェクトの中でデータを隠蔽し、最低限のアクセス手段のみを公開する「カピセル化」を実装する必要があります。
今回はプロパティについて紹介します。
プロパティ
フィールドや定をprivateにすることで、クラス外部からは容易にアクセスできないようにカプセル化することができます。
1 2 3 4 5 6 7 8 9 10 |
class Television { private bool power; // 電源の状態 private int channel; // 現在のチャンネル private int volume; // 現在の音量 private const int ChannelMin = 1; // チャンネル下限 private const int ChannelMax = 12; // チャンネル上限 private const int VolumeMin = 0; // 音量下限 private const int VolumeMax = 40; // 音量上限 } |
publicと違ってprivateにすることでmainメソッドで作成したインスタンスに
アクセスできなくなってしまいます。
このように、隠蔽されたデータにアクセスする場合には、「プロパティ」を使います。
アクセサー
プロパティは次の構文のように、getアクセサーとsetアクセサーを使ってフィールドの値にアクセスします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
アクセス修飾子 データ型 プロパティ名 { get { プロパティ取得時に実行する処理 return フィールド名; } // getアクセサー: フィールドをェックして返す set { プロパティ設定時に実行する処理 フィールド名 = value; } // setアクセサー: 値をチェックしてフィールドに設定する } |
プロパティのアクセス修飾子は一般にpublicです。getで始まるブロックを「get アクセサー」setで始まるブロックを「setアクセサー」と呼びます。setアクセサーに記述されている「value」は、プロパティをとおしてフィールドに代入される値 です。このvalueは宣言なしに使用することができ、常にこの名前で用います。
プロパティの定義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
lass Television { private bool power; // 電源の状態 private int channel; // 現在のチャンネル private int volume; // 現在の音量 private const int ChannelMin = 1; // チャンネル下限 private const int ChannelMax = 12; // チャンネル上限 private const int VolumeMin = 0; // 音量下限 private const int VolumeMax = 40; // 音量上限 //プロパティ public bool Power { get { return power; } set { power = value; } } public int Channel { get { return channel; } set { if (value >= Channel Min && value <= Channel Max) channel = value; } } public int Volume{ get { return volume; } set { if (value >= VolumeMin && value <= VolumeMax) volume = value; } } //メソッド //テレビの電源をON/OFF public void OnOFF() { if (power == true) power = false; // 電源OFF else power = true; // 電源ON } |
フィールドのchannelとvolumeは上下限値が決まっています。
アクセサーでチェックして、その範囲内のvalueのみフィールドに代入するようにしています。
main側も修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
static void Main(string[] args) { Television tv = new Television (); Console.WriteLine("10チャンネルを設定します。"); tv.Channel = 10; Console.WriteLine($"TVは { tv.channel } チャンネルです。"); Console.WriteLine("チャンネルを+2します。"); tv.ChannelUP(); tv.ChannelUP(); Console.WriteLine($"TVは {{ tv.channel }チャンネルです。"); Console.WriteLine("チャンネルを-1します。"); tv.Channel Down (); Console.WriteLine($"TVは { tv.channel }チャンネルです。"); } |
プロバティは、オブジェクトを使用する側からはフィールドのように見えますが、クラスを実装する側ではメソッドのように振る舞います。
なお、getアクセサーとset アクセサーには異なるアクセスレベルを指定でき、Setの前にprivateを書くと外からセットできないフィールドになります。
setアクセサーを実装せずに読み取り専用のプロパティにすることもできます。通常、テレビの電源と音量を外部から直接指定することはありませんね。ですから、TelevisionクラスのPowerと Volumeは、次のように読み取り専用のプロパティに書き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
private int channel; // 現在のチャンネル private int volume; // 現在の音量 //省略 public bool Power { get { return power; } } public int Volume { get { return volume; } } <h3 class="blog_h3">自動実装プロパティ</h3> <p class="blog_p">C#3.0からサポートされた自動実装プロパティを使うと、非常に簡潔にプロパティを定義できます。 </p> <p class="blog_p">自動実装プロパティ</p> <pre class="lang:default decode:true "> アクセス修飾子 データ型 プロパティ名 { get; set; } |
自動実装プロパティを宣言すると、コンパイル時にフィールドが内部に自動的に作成されるので、プログラムにフィールドを記述する必要がなくなります。もし、値の取得のみを行いたい場合には、次のようにsetの前にprivateを付けて外部からはsetができないようにしてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
public string Name { get; private set; } <pre class="lang:default decode:true "> class Television { // 自動的に内部でフィールドが生成されるので、powerとvolumeを削除する private int channel; // 現在のチャンネル」 private const int ChannelMin = 1; // チャンネル下限 private const int ChannelMax = 12; // チャンネル上限 private const int VolumeMin = 0; // 音量下限 private const int VolumeMax = 40; // 音量上限 // 自動実装プロパティに変更 public bool Power { get; private set; } // プロパティ public int Volume { get; private set; } // テレビのON/OFF状態 public int Channel // 現在のチャンネル { get { return channel; } set { if (value >= Channel Min && value <= Channel Max) channel = value; } } // メソッド // テレビの電源をON/OFFする public void OnOFF() { //フィールドのpowerを削除したので、プロパティを使ってアクセスするように修正 if (Power = = true) Power = false; // 電源OFF else Power = true; // 電源ON } // チャンネルを+1する public void ChannelUP() { // フィールドから削除したpowerとvolumeに合わせて、channelもプロパティを使って アクセスするように修正 if ( Channel < ChannelMax) Channel++; } // チャンネルを-1する public void Channel Down () { if (Channel > Channel Min) Channel --; } // 音量を上げる public void VolumeUP() { // フィールドのvolumeを削除したのでプロパティを使ってアクセスするように修正 if (Volume < VolumeMax) Volume++; } // 音量を下げる public void Volume Down () { // フィールドのvolumeを削除したのでプロパティを使ってアクセスするように修正 if (Volume > VolumeMin) Volume--; } } |

壷井
株式会社flyhawkの壷井です。フライテックメディア事業部でのメディア運営・ライター業務なども担当。愛機はMac Book AirとThinkPad。好きな言語:swift、JS系(Node.js等)。好きなサーバー:AWS。受託開発やプログラミングスクールの運営をしております。ご気軽にお問い合わせください。