1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-11-12

記事の書かれ方について

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

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

4部構成です

Part.1 さっくりインスタンス生成をしてみる
Part.2 コンストラクタを使ってもっとすっきり
Part.3 アクセス制御をして、入ってくる値を制限しよう ←イマココ
Part.4 クラス変数・メソッドを使ってみる

つなぎ

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

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);
  }
}

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

アクセス制限をしよう!

アクセス制限と聞くと、なんか縛りを設けるんやろなぁ...という感じがすると思う。そんな感じでおk。
privatepublicを付けてやることで変数やメソッド、コンストラクタに対してアクセスを制限することができるのです!!

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

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

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

書いてみる

numnameprivateアクセス修飾子を付けてみよう。

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);
  }
}

これを使うのを書く。

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となる。

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

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

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

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

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

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

そう。ヤバいんですよ。(語彙が少ない)

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

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

ゲッタ/セッタを作る

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

ゲッタ/セッタは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;
  }
}

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

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箇所だけ確認すればいいので修正が楽になるんです!!

ちなみに

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

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

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

次回

次はクラス変数、クラスメソッドを使っていろんな場所から同じオブジェクトにアクセスしてみよう!
つぎ → Part.4 クラス変数・メソッドを使ってみる

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?