LoginSignup
1
1

More than 5 years have passed since last update.

Java学習ノート_140714_2(継承)

Posted at

継承(クラスとオブジェクト)

オブジェクト指向プログラミング(OOP)とは、データとその操作方法を一緒にしたオブジェクト(Javaの場合はクラス)を利用したプログラム技法のこと。Smalltalkのアラン・ケイ(名付け親)とC++のビャーネ・ストロヴストルップ(特徴を再定義)が影響を与えたと言われる。

特徴

  1. カプセル化
  2. 継承
  3. ポリモーフィズム(多態性)

カプセル化については、アクセス修飾子とかセッタゲッタ(どうでもいいけど、雪駄下駄って出ると日本だなぁって思う)あたりで半分くらいは理解できてる気がするので、継承から進むようだ。

継承は、クラスの機能を他のクラスが引続ぐ仕組み。親子のような関係。継承元をスーパークラス(親クラス)、継承するクラスはサブクラス(子クラス)。継承を用いて、同一の機能を省略していく記述方法を差分プログラミングと呼ぶ。

スーパークラスから継承したメソッドを上書きすることを、メソッドのオーバーライド(再定義)と呼ぶ。オーバーロード(多重定義)は同一クラス内の引数の異なるメソッドを複数定義すること。ライドでスーパークラスに乗るイメージ、とのこと。

フィールドの再定義はオーバーライドとは呼ばない。ポリモーフィズムは単に上書きのことを言うわけではない。staticメソッドの再定義もできるが、あまり推奨はされない。

上記機能を試してみた。

Animal.java
/*
 *  動物クラス
 */
public class Animal {
    String favorite = "worm";

    void sleep(){
        System.out.println(getClass().getName() + " is sleeping normally now..." );
    }
}
Ape.java
/*
 *  猿クラス(動物クラスから継承)
 */
public class Ape extends Animal{
    String favorite = "banana";

    void sleep(){
        System.out.println("Ape is sleeping on the tree now.....");
        super.sleep();
    }
}
Human.java
/*
 *  人間クラス(猿クラスから継承)
 */
public class Human extends Ape {
    String favorite = "beef";
    String item = "PC";

    void sleep(){
        System.out.println("Human is sleeping on the bed now.....");
    }
    void eatAndSleep(){
        System.out.println(getClass().getName() + " is eating " + favorite +"." );
        sleep();
        super.sleep();
    }
}
OOPSample.java
public class OOPSample {
    public static void main(String[] args) {

        Animal animal = new Animal();
        System.out.println("### " + animal.getClass().getName() + " ###");
        //System.out.println(animal.favorite);
        animal.sleep();

        Ape ape = new Ape();
        System.out.println("### " + ape.getClass().getName() + " ###");
        //System.out.println(ape.favorite);
        ape.sleep();

        Human human = new Human();
        System.out.println("### " + human.getClass().getName() + " ###");
        //System.out.println(human.favorite);
        human.eatAndSleep();
    }
}

実行結果

### Animal ###
Animal is sleeping normally now...
### Ape ###
Ape is sleeping on the tree now.....
Ape is sleeping normally now...
### Human ###
Human is eating beef.
Human is sleeping on the bed now.....
Ape is sleeping on the tree now.....
Human is sleeping normally now...

オーバーライドの制限

final修飾子がついたメソッドはオーバーライドできない。また、オーバーライドした際、元のメソッドで定義されているアクセス修飾子と同じか、またはゆるい宣言でなければならない。スーパークラスでprivateのメソッドは継承できない。同じシグネチャのメソッドを定義できるが、別メソッドの定義として扱われる。

スーパークラスのstaticなメソッドと同名の非staticなメソッドをサブクラスで定義することができない。非staticメソッドをstaticメソッドでオーバーライドすることもできない。throwsによる例外宣言も継承できるが、限定的な形になる(例外をなんでもスローできるわけではない)。

final修飾子

final修飾子をつけることで、クラス、また個別のメソッドの継承を禁止することができる。フィールドにfinal修飾子をつけた場合は、オーバーライドと継承を禁止するということではなく、代入(または初期化)時の値を変更できないということを表す。

継承とコンストラクタ、super()

コンストラクタ(他にはprivateなメンバ)は継承されない。コンストラクタ内でsuper()を宣言すると、スーパークラスのコンストラクタを明示的に呼び出すことができる。superはコンストラクタ内で最初に呼び出される必要がある(あとにするとエラーが出る、納得)。

is or has

isで考えられる場合は継承関係、hasの場合は、メンバとして考えると、実装のときに迷わないらしい。

問題

メンバにwidth, height getArea()を持ったRectクラスを継承した、Cubeクラスで奥行きdepthと体積を求めるgetVolumeを定義して使用するサンプルを作成する。

Rect.java
public class Rect {
    int width, height = 0;
    public int getArea(){
        return width * height;
    }
}
Cube.java
public class Cube extends Rect {
    int depth = 0;
    public int getVolume() {
        return getArea() * depth;
    }
}
CubeSample.java
public class CubeSample {
    public static void main(String[] args) {
        Cube cube = new Cube();
        cube.width = 10;
        cube.height= 20;
        cube.depth = 30;
        System.out.println(cube.getVolume());
    }
}

より整理して書くと以下。

Rect.java
class Rect {
    int width, height = 0;
    Rect(int x, int y) {
        width = x;
        height = y;
    }
    int getArea(){
        return width * height;
    }
}
Cube.java
 class Cube extends Rect {
    int depth = 0;
    Cube(int x, int y, int z) {
        super(x, y);
        depth = z;
    }
    public int getVolume() {
        return getArea() * depth;
    }
}
CubeSample.java
public class CubeSample {
    public static void main(String[] args) {
        Cube cube = new Cube(10,20,30);
        System.out.println(cube.getVolume());
    }
}
1
1
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
1