【C#入門】オブジェクト指向の『カプセル化』についてまとめた

>この記事では、《オブジェクト指向の『カプセル化』》について、
業務を通して学習した内容を、備忘録としてまとめています。

- __『カプセル化』とは…？__
- __『カプセル化』すると何がいいのか…？__
- __フィールドの設定方法__

こういった内容についてまとめています。

__※本記事は、自分で学習したことのまとめ用として書いています。
尚、解説で誤った点があれば、スローして頂ければ喜んでキャッチしますのでお願い致します。__

## 【概要】&ensp;『カプセル化』&ensp;とは…？

![capsule_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255884/5b7ef2c3-cc97-dfaf-df14-133788f22246.jpeg)

クラス内のフィールド（メンバー変数）を`private`で宣言することで…

__外部からの値の参照・変更を制限__することができます。

変数を、クラスで包む、囲むイメージ。

>『フィールド』とは・・・
クラスのメンバー変数として定義され、クラス内に直接書かれる変数のことで、フィールドと呼ばれます。
『フィールド』は、クラス内のメソッドから参照可能です。

例えば、下記のように記述します。

~~~cs
namespace Sample
{
    public class Program
    {
        private int _num = 0;

        public Program(int num)
        {
            _num = num;
        }
    }
}
~~~

上記はコードは・・・

`_num`変数が`private`のフィールドで宣言されており、カプセル化されている状態です。

この`_num`を変更するためには…

コンストラクタで`int`型の値を指定することで、`_num`の初期値を変更することができます。

## 【メリット】&ensp;『カプセル化』&ensp;すると何がいいのか…？

![list_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255884/055d6913-143d-62f5-3543-661b74afa7d0.jpeg)

- __コードが理解しやすく（読みやすく）なる__
 - 値とロジックを１つにまとめることができる
- __不正な値が設定されることを防げる__
- __保守性が高くなる__

『カプセル化』をすると、__外部からの値の参照・変更が制限される__ため、宣言しているフィールドに設定される値は、必ず自分自身のクラスで設定する必要があります。

そのため・・・

__そのフィールドにどういった値が設定されるかは、そのクラスを読むだけで理解できるようになります。__

また・・・

外部からフィールドを設定することを許可してしまうと、意図していない（許可したくない）値が設定される可能性があります。

そこで・・・

『カプセル化』をすることで、__不正な値が設定されることを、事前に防ぐことが可能__です。

## 『カプセル化』したフィールドの設定方法｜外部から変更する

![capsule_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255884/e74fba61-398c-f594-5c12-629513163ad8.jpeg)

繰り返しになりますが…

『カプセル化』をすることで、__外部からの値の参照・変更を制限__することができます。

ですが・・・

外部から値を設定できないので、クラスとしては機能しなくなります。

そのため・・・

何らかの方法で、外部からの値の変更を可能にする必要があります。

『カプセル化』されているフィールドの値を外部から変更する方法は…

1. &ensp;__コンストラクタ__
2. &ensp;__プロパティ__

を使った２つの方法があります。

### 方法①：&ensp;コンストラクタ

先ほど少し紹介しましたが…

__コンストラクタでフィールドのの初期値を変更することができます。__

~~~cs
namespace Sample
{
    public class Program
    {
        private int _num = 0;

        public Program(int num)
        {
            _num = num;
        }
    }
}
~~~

上記はコードは・・・

`_num`変数が`private`のフィールドで宣言されており、カプセル化されている状態です。

この`_num`を変更するために…

コンストラクタで`int`型の値を指定することで、`_num`の初期値を変更しています。

### 方法②：&ensp;プロパティ

値を設定するメソッドを公開する。

コンストラクタで設定する方法は、クラスを生成するときにしか動作しないため、初期値しか指定することができません。

生成後に値を変更したくても、コンストラクタだけでは対応できません。

そこで・・・

値を変更することのできるメソッドを公開するやり方があります。

~~~cs
namespace Sample
{
    public class Program
    {
        private int _num = 0;

        public int Num
        {
            set { _num = value; } //値の代入
            get { return _num; } //外部に値を返す
        }
    }
}
~~~

`set{}`の中には…

~~~cs
フィールド（メンバー変数） = value
~~~

というように記述します。

`value`は、利用者側のクラスで代入された値が格納される『予約語』になります。

また・・・

`get{}`の中には…

~~~~cs
return フィールド（メンバー変数）
~~~

というように、戻り値を記述します。

#### 【補足】&ensp;C#3.0での書き方

C#3.0では、プロパティの`set`、`get`の中身を省略して記述できるようになりました。

ちなみに・・・

この機能を『自動プロパティ』と言います。

~~~cs
namespace Sample
{
    public class Program
    {
        private int _num = 0;

        public int Num { set; get; }
    }
}
~~~

#### 【補足】&ensp;C#6.0での書き方

C#６.0では、初期値を指定できるようになりました。

~~~cs
public int Num { get; set; } = 100
~~~

ちなみに・・・

上記のコードは、以下と同様になります。

~~~cs
private int _num = 100;

public int Num
{
    set { _num = value; }
    get { return _num; } 
}
~~~