Java - クラス・インスタンス生成 Part.3

# 記事の書かれ方について
授業スライドとかを参考にしてるわけじゃないので、別の切り口から説明されてると思うけど。
たぶん言ってることはあっている（はず）。

アドリブなのでミスがあるかもしれないのであったら教えて！

## 4部構成です
[Part.1 さっくりインスタンス生成をしてみる](https://qiita.com/okmt_okmt_/private/5801bc2930b54e9e6559)
[Part.2 コンストラクタを使ってもっとすっきり](https://qiita.com/okmt_okmt_/private/9b862a4a94aae00298fb)
[Part.3 アクセス制御をして、入ってくる値を制限しよう](https://qiita.com/okmt_okmt_/private/ef595bb940c616785564) ←ｲﾏｺｺ
[Part.4 クラス変数・メソッドを使ってみる](https://qiita.com/okmt_okmt_/private/f185ad6bc1a47fc1c0c6)

# つなぎ
Part.2 ではコンストラクタを実装した。
コンストラクタはインスタンスが生成されたときに一度だけ実行される特殊なメソッドのこと。
コンストラクタはクラスの名前を書いてやることで実装できる。

```java:DigitalStudentCard.java
class DigitalStudentCard{
  //学籍番号
  int num;

  //お名前
  String name;

  //コンストラクタ
  DigitalStudentCard(int num, String name){
    //引数のnumをインスタンスのnum(this.num)へ代入
    this.num = num;

    //同じく
    this.name = name;
  }

  //出力する用のメソッド（自己紹介してもらう)
  String getSelfIntroduction(){
    return "学籍番号 : " + num + " 名前 : " + name);
  }
}
```

コンストラクタの勝手はほぼメソッドと同じなので似たような感覚で書いていいと思う。

# アクセス制限をしよう！
アクセス制限と聞くと、<b>なんか縛りを設けるんやろなぁ...</b>という感じがすると思う。そんな感じでおｋ。
`private`や`public`を付けてやることで変数やメソッド、コンストラクタに対してアクセスを制限することができるのです！！

こういうキーワードのことを<b>アクセス修飾子</b>なんて言ったりするけど
だいたいみんなは「privateにしたら？」とか「publicじゃないんじゃない？」とか言ったりしてます。

そんなアクセス修飾子の種類は以下の通り。

| 修飾子 | 効能 |
|:-:|:-:|
| public | どこからでもアクセスできる |
| （何も書かない） | パッケージ内のどこからでもアクセスできる。（いつか説明する） |
| protected | `extends`や`implements`による親子関係がある場合にのみアクセスできる。（いつか説明する） |
| private | そのクラス、インスタンスからのみアクセスできる。 |

# 書いてみる

`num`と`name`に`private`アクセス修飾子を付けてみよう。

```DigitalStudentCard.java
class DigitalStudentCard{
  //学籍番号
  private int num;

  //お名前
  private String name;

  //コンストラクタ
  DigitalStudentCard(int num, String name){
    //引数のnumをインスタンスのnum(this.num)へ代入
    this.num = num;

    //同じく
    this.name = name;
  }

  //出力する用のメソッド（自己紹介してもらう)
  String getSelfIntroduction(){
    return "学籍番号 : " + num + " 名前 : " + name);
  }
}
```

これを使うのを書く。

```java
class UseClass{
  public static void main(String[] args){

    //インスタンス生成
    DigitalStudentCardtanaka = new DigitalStudentCard(118114, "田中角栄");

    //別のインスタンスを生成
    DigitalStudentCardnoguchi = new DigitalStudentCard(118514, "野口英世");

    //出力
    System.out.println(tanaka.getSelfIntroduction);
        // 学籍番号 : 118114 名前 : 田中角栄

    System.out.println(noguchi.getSelfIntroduction);
        // 学籍番号 : 118514 名前 : 野口英世
  }
}

```

この例では何も変わらないけど、次のような書き方がNGとなる。

```java
tanaka.num = 114514;
    //コンパイルエラー

tanaka.name = "田中角栄";
    //コンパイルエラー
```

`num`と`name`をインスタンス内部でないとアクセスできないように`private`アクセス修飾子で制限したのでこれらができなくなる。

# なんでこんな面倒くさいことが必要なの？

「どっからでもアクセスできた方が便利だし、楽でいいじゃーん」

確かに、制約を設けない方が好きな書き方ができていいように思える。
けど、<b>好き放題できる</b>ってヤバそうに聞こえない？

そう。ヤバいんですよ。（語彙が少ない）

これがマジモンの学生証だとしたら勝手に学籍番号とか名前を書き換えられちゃたまらないでしょう。
変えるにしても、番号とか名前とか、従ってほしいルールがあるはず。

そのようなルールを設けるために<b>ゲッタ(Getter) / セッタ(Setter)</b>と呼ばれるメソッドを実装しよう。

# ゲッタ/セッタを作る
「こう呼ばれてる」ってだけで、別に<b>特殊なメソッドの書き方をするってことではない</b>ので安心してほしい。
今までもよく見かけてきたああいう書き方でっせ。

ゲッタ/セッタは`get〇〇()`、`set〇〇()`と名付けるのが無難。

```DigitalStudentCard.java
class DigitalStudentCard{
  //学籍番号
  private int num;

  //お名前
  private String name;

  //コンストラクタ
  DigitalStudentCard(int num, String name){  
    //せっかく作ったのでゲッタを使う
    setNum(num);

    //同じく
    setName(name);
  }

  //出力する用のメソッド（自己紹介してもらう)
  String getSelfIntroduction(){
    return "学籍番号 : " + num + " 名前 : " + name);
  }

  // ----- 追加 -----

  //numを返すだけのメソッド（ゲッタ）
  int getNum(){
    return num;
  }

  //nameを返すだけのメソッド（ゲッタ）
  String getName(){
    return name;
  }

  //numを設定するメソッド（セッタ）
  void setNum(int number){
    //うちの学校の学籍番号を例にして考えてみる
    //何となく年っぽくなってるとこを抜き出す
    int year = number/1000;

    //119を超える値を禁止する
    if(year > 118){
      year = 118;
    }

    //番号っぽいとこだけ抜き出す
    number = number%1000;

    //3桁に収めたいので999を超える値は999にする
    if(number > 999){
      number = 999;
    }

    //くっつけて返す
    return year*1000 + number;
  }

  //nameを設定するメソッド（セッタ）
  void setName(String name){
    this.name = name;
  }
}
```

今度はこれらのメソッドを呼び出してみよう。

```java
class UseClass{
  public static void main(String[] args){
    //インスタンス生成
    DigitalStudentCardtanaka = new DigitalStudentCard(118114, "田中角栄");

    //num変数の値を表示
    System.out.println(tanaka.getNum());
        // >> 118114

    //name変数の値を表示
    System.out.println(tanaka.getName());
        // 田中角栄

    //num変数の値を変更
    tanaka.setNum(200, 1000);
        // わざと大きい値を入れてみる

    //name変数の値を変更
    tanaka.setName("たなかかくえい");
        // ネタが思い浮かばなかったのでとりまひらがなに


    System.out.println(tanaka.getNum());
        // 118999
    System.out.println(tanaka.getName());
        // たなかかくえい
  }
}
```

こうしてやることで、`nun`だけ欲しい！`name`だけ欲しい！なんて時は`getNum()`や`getName()`を使うことで対応できる。

のっぴきならぬ事情で学籍番号変えたいな～とか、結婚して名字が変わったなんてときは`setNum()`や`setName()`を使って設定ができる。

学籍番号はメチャメチャな値を入れられたら困るので、適切な値であるかを確認する仕組みを作っている。
変数`num`に入る値を限定できるので、無法地帯と化すことを避けられる。

コンストラクタでも`setNum()`、`setName()`を使っているので代入処理を行っている部分を一か所だけにすることができた。
こうすることで後々、バグがあったとしても1箇所だけ確認すればいいので修正が楽になるんです！！

# ちなみに
アクセス修飾子はメソッドや、コンストラクタにも用いることができる。

```java
private void setName(String name){
  //なんか処理
}
```

アクセスできる範囲は変数同様にそのクラス・インスタンス内のみに限定される。

# 次回
次はクラス変数、クラスメソッドを使っていろんな場所から同じオブジェクトにアクセスしてみよう！
つぎ → [Part.4 クラス変数・メソッドを使ってみる](https://qiita.com/okmt_okmt_/private/f185ad6bc1a47fc1c0c6)