【Java】スーパークラスとサブクラス

スーパークラスとサブクラスとは

クラスは拡張することができます。すでに存在するクラスをもとにして、それに新しいメソッドやフィールドを追加したり上書きしたりして新しいクラスを宣言することができます。クラスを拡張してできた新しいクラスを、もとのクラスのサブクラスと呼びます。また逆に、元のクラスを、拡張してできたクラスのスーパークラスと呼びます。

extendsでスーパークラスを指定

それでは長方形大きさや面積、周長を定義したクラスRectを宣言します。次に立方体の大きさや表面積、体積を定義したクラスBoxを宣言します。継承を行うためにはextendsを使用します。クラス名の後ろにextendsを記述し継承したいクラスを指定します。ここではboxというクラスを宣言しています。後ろにextends Rectと記述しています。このように書くことでBoxがRectのサブクラスであることを表します。

public class Box extends Rect{
	.....
}
/*
継承の構文
class サブクラス名 extends スーパークラス名{
    .....
}
*/

継承とは

サブクラスは、スーパークラスのフィールドとメソッドを受け継ぎます。このことを継承といいます。フィールドとメソッドは継承されますが、コンストラクタは継承されません。これはJava言語の文法規則です。それでは長方形を定義するクラスRectのフィールドとメソッドを継承して立方体を定義するクラスを記述してみます。

public class Rect{

	//フィールド
	private int width; //幅
	private int height; //高さ
	
	//デフォルトコンストラクター
	public Rect(){
		this(0,0);
	}
	
	
	//コンストラクター
	public Rect(int width, int height) {
		this.width = width;
		this.height = height;
	}
	
	//メソッド
	//面積を計算
	public int calcArea(){
		return this.width * this.height;
	}
	
	//周りの長さ
	public int calcLength(){
		return (this.width + this.height) * 2;
	}
	
	//getter & setter
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
}

スーパークラスを継承する

クラスRectのサブクラスであるクラスBoxにはクラスRectのコンストラクタは継承されないので、フィールドに奥行きの情報を加えて立方体を定義するコンストラクタを生成します。

public class Box extends Rect{
	
	//フィールド設定
	private int length; //奥行き
	
	//デフォルトコンストラクター
	public Box(){
		this(0,0,0);
	}
	
	//コンストラクター
	public Box(int width,int height,int length){
		super(width,height);
		this.length = length;
	}
	.....
}

スーパークラスの呼び出し

立方体の面積を計算するのに、長方形で定義したクラスRectのメソッドcalcAreaとフィールドwidth、heightを継承をつかって呼び出します。スーパークラスのフィールドやメソッドを呼び出すにはsuperの後にフィール名やメソッド名を.ピリオドでつなぎます。

public class Box extends Rect{
    .....
    //表面積の計算
	public int calcArea(){
		return (super.calcArea() * 2) + (this.length * super.getHeight() *2) + (this.length * super.getWidth() * 2);
	}
}
public class Box extends Rect{
    .....
    //全周の長さ
	public int calcLength() {
		return (super.calcLength()*2) + (this.length * 4);
	}
}

インターフェースによる多重継承

Java言語では多重継承はサポートされていませんが、インターフェースという仕組みを使うことで擬似的に多重継承を実現することができます。

インターフェースとは

クラスは参照型の一種で、名前やフィールド、メソッドを持ち、スーパークラスやサブクラスを持っています。インターフェースも参照型の一種です。名前やフィールドを持ち、スーパーインターフェースやサブインターフェースを持ちます。クラスとインターフェースの違いは、次の点で異なります。
・インターフェースが持つフィールドは必ず定数
・インターフェースが持つメソッドは必ず抽象メソッド()
※抽象メソッド:{中括弧}内に具体的な処理を記述しないメソッド
・インターフェースはインスタンスをつくることができない

インターフェースの宣言

それでは実際にインターフェースをつかってみます。新しく立方体の体積を計算するクラス、ここで言うインターフェースをつくります。
interfaceという単語は、Java言語の予約語で、インターフェースの宣言の始まりを表します。宣言されたメソッドには本体({中括弧}でくくられた部分)がない抽象メソッドになります。interfaceの中に宣言されているメソッドはabstractが付いていなくても自動的に抽象メソッドになります。つまり、interfaceのなかに{中括弧}があるメソッドは宣言できないということです。

public interface ThreeD {
    //体積を計算するための抽象メソッド
	public int calcVolume();
}

インターフェースの実装

インターフェースの実装にはimplementsという予約語を使います。
それでは、先程の立方体の表面積や周長を計算するクラスBoxにインターフェースThreeDを実装してみます。

//implements - インターフェース、extend - 継承
public class Box extends Rect implements ThreeD {
	.....
	//体積を求める
	public int calcVolume(){
        //インターフェースで宣言された抽象メソッドに具体的なメソッドを記述します
		return super.calcArea() * this.length;
	}
}

完成

Java言語でプログラムを書くということは、クラスを宣言し、フィールドを作り、メソッドを設計して、それを実装することです。もしも、過去に作られたクラスを全く利用できなかったら、すべてをゼロからプログラミングしなければなりません。スーパークラスのフィールドやメソッドを継承することで、同じフィールドやメソッドを再度プログラミングするひつようが無くなるのです。

public class Box extends Rect implements ThreeD {
	
	//1フィールド設定
	private int length; //奥行き
	
	//2デフォルトコンストラクター
	public Box(){
		this(0,0,0);
	}
	
	//2コンストラクター
	
	public Box(int width,int height,int length){
		super(width,height);
		this.length = length;
	}
	

	//メソッド
	//表面積の計算
	public int calcArea(){
		return (super.calcArea() * 2) + (this.length * super.getHeight() *2) + (this.length * super.getWidth() * 2);
	}

	//全周の長さ
	public int calcLength() {
		return (super.calcLength()*2) + (this.length * 4);
	}

	//体積を求める
	public int calcVolume(){
        //インターフェースで宣言された抽象メソッドに具体的なメソッドを記述します
		return super.calcArea() * this.length;
	}
}
public class Sample {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		//Rectを利用
		System.out.println("Rectを利用");
		Rect rect = new Rect(); //インスタンス化
		rect.setWidth(10);
		rect.setHeight(20);
		
		System.out.println("幅=" + rect.getWidth());
		System.out.println("高さ=" + rect.getHeight());
		
		System.out.println("面積=" + rect.calcArea());
		System.out.println("周りの長さ=" + rect.calcLength());
		
		Box box = new Box(5,5,10);
		System.out.println("面積=" + box.calcArea());
		System.out.println("周りの長さ=" + box.calcLength());
		System.out.println("体積=" + box.calcVolume());
	}

}