Help us understand the problem. What is going on with this article?

【Java】クラスやメンバの頭に付けるいろいろまとめ

More than 1 year has passed since last update.

静的メンバ

頭にstaticを入れるだけ。
下記の例は複数の人間で一つの財布を持っているようなイメージ。
この場合、それぞれのHumanインスタンスh1,h2がフィールドを持っているのではなく、Humanクラスがフィールドを持っているという考え方。
なので静的フィールドはクラス変数とも言われる。

Human.java
public class Human{
     static int money=100;
}
Main.java
public class Main{
     public static void main(String[] args){
          // 一つ目のインスタンスを作成
          Human h1 = new Human();
          // 二つ目のインスタンスを作成
          Human h2 = new Human();

          // h1.moneyクラス変数を書き換え
          h1.money=200;

          // h2.money変数を表示
          System.out.println(h2.money);
          // moneyはクラス変数だから200と表示されるはず
     }
}

静的メソッドはインスタンスを生成しなくても呼び出せる。
だから、上の例で言うと、いきなり

Main.java
System.out.println(Human.money);

とか書いても大丈夫。
mainメソッドが静的メソッドなのもそういう理由。

カプセル化

カプセル化を実現する一つの方法として、アクセス修飾子をクラスやメンバに付けて可視性を設定する。

  • public:すべてのクラス
  • protected:自分と同じパッケージに属するか、自分を継承したクラス
  • packaged private(デフォルト):自分と同じパッケージに属するクラス
  • private:自分自身のクラスのみ
Test.java
public class Test{
     private int i=1;
     public void calc(int j){
          return this.i+j;
     }
}

getterとsetter

フィールドはprivate、メソッドはpublicに設定し、getterとsetterで値を受け渡す方法の基本的な書き方。

Test.java
public class Test{
    private int num;

    public int getNum(){
        return this.num;
    }

    public void setNum(int num){
        this.num = num;
    }
}

継承・実装

  • 継承:exetends
  • 実装:implements

抽象クラスの頭に付けるabstractが取れるのは抽象部分がオーバーライドされ尽くした時。

継承(exetends)

ここではInuShibainuという継承関係。
なお、osuwariメソッドは抽象化されているのでShibainuクラスでオーバーライドされる必要がある。

Inu.java
public abstract class Inu{
    public void ote(){
        System.out.println("左手を差し出す");
    }

    public abstract void osuwari();
        // ここは何も書かない
}
Shibainu.java
public class Shibainu extends Inu{
    public void osuwari(){
        System.out.println("地面に座る");
    }

    public void mate(){
        System.out.println("ご飯を我慢する");
    }
}
Main.java
public class Main{
    public static void main(Strgin[] args){
        Shibainu dog = new Shibainu();

        dog.ote();      // Inu由来メソッド
        dog.osuwari();  // Inu(←Shibainu)由来メソッド
        dog.mate();     // Shibainu由来メソッド
    }
}

多態性を利用して、

Main.java
Inu dog = new Shibainu();

dog.osuwari();

ということもできる。

この場合、呼び出すことのできるメソッドはInuクラスが持っているものだけになる。
ゆえに、実際に生成されるインスタンスがShibainuでもdog.mateは呼び出せない。
osuwariメソッドが呼び出された場合は、Inuの方ではなく、Shibainuの方のメソッドが処理される。

こうした多態性を利用して、以下のような処理も書ける。

Main.java
Inu[] dogs = new Inu[3];

Inu[0] = new Shibainu();
Inu[1] = new Akitaken();
Inu[2] = new Tosaken();

for (Inu d: dogs){
    d.osuwari();
}

「地面に座る」「寝る」「言うことを聞かない」など、同じmateメソッドでもクラスによってメソッドの中身が違う場合にとても便利。

継承に関してはコンストラクタに注意する必要がある。
superを使って明示的に引数を与えてやらないといけない時があるからだ。
ここで使うsuperは子クラスのメソッド内で親クラスのメソッドを呼び出すときのsuperとは別物と認識していた方がいい(これはthisでも同じ)。

実装(implements)

クラスをインターフェイスにできる条件は2点。

  • すべてのメソッドが抽象メソッドであること。
  • 基本的にフィールドを一つも持たない。

「基本的に」とあるのは、public static finalが付いたフィールド(定数)だけは宣言が許されるため。ただその場合はpublic static finalは省略可にしてもいい。

classではなく、interfaceと宣言する。

Animal.java
public interface Animal{
    void run();
}
Inu.java
public class Neko implements Animal{
    void run(){
        System.out.println("4本足で走る");
    }
}

インターフェースは多重実装が許されるので

Neko.java
public calss Neko extends Mammal implements Animal, Organic{
    // MammalクラスとAnimalインターフェースとOrganicインターフェースを親に持つ。
}

こういう書き方もできる。
猫クラスは哺乳類クラスを親に持ち、動物と有機物のインターフェースを持つ、という感じ。あんまり上手い例ではない。

インターフェース・抽象メソッドの美点は

  • オーバーライドを強制させられる。
  • 意図しないインスタンス化が避けられる。
  • 何もしないメソッドと明確に区別できる。

といったところ。

参考書籍

スッキリわかるJava入門第二版
Pp.332-524

shg3
学習
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away