Javaでinstanceofの使いみちを誤っていた話。スーパークラスに詰め込んでからよね...

Javaで、instanceof ってあるあるだよね~、からの、使い方を誤っていました...

そんな反省の意味を込めて、今日もJava を。

そして、なんだかんだで、Javaに関する記事が99回目になりました。毎回、どうしようもない記事ばかりが多くなっているのですが、読んでくださっている皆様ありがとうございます。次回が100回目なんだけども、少しはまともな記事を書きたい...どうもボクです。

というわけで、レッツ~トライ。

 

スーパークラスに詰め込んで~

「ナイフ ランプ鞄に 詰め込んで 父さんが残した 熱い想い母さんがくれた あのまなざし.」 という、『天空の城ラピュタ』の「君をのせて」の歌詞が出たところで、スーパークラスに詰め込もうじゃないですか、サブクラスたちを。

というわけで、Eclipseを起動し、Javaプロジェクトを作成し、適当なクラスを作成。

f:id:ts0818:20190207202253p:plain

ソースはこんな感じ。フィールドとかコンストラクタとか超適当なクラス構成です。

SuperMan.javaスーパークラス

package dto;

public class SuperMan {

	private String name;

	private String from;

	public SuperMan() {

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getFrom() {
		return from;
	}

	public void setFrom(String from) {
		this.from = from;
	}
}

Sub.java ← サブクラス

package dto;

public class Sub extends SuperMan {

	private String hobby;

	private int power;

	public Sub() {
		super();
	}

	public String getHobby() {
		return hobby;
	}

	public void setHobby(String hobby) {
		this.hobby = hobby;
	}

	public int getPower() {
		return power;
	}

	public void setPower(int power) {
		this.power = power;
	}
}

IppMan.java ← サブクラス

package dto;

public class IppMan extends SuperMan {

	private String syonento;

	private String jinkyo;

	private String Hyoshi;

	private int power;

	public IppMan() {
		super();
	}

	public String getSyonento() {
		return syonento;
	}

	public void setSyonento(String syonento) {
		this.syonento = syonento;
	}

	public String getJinkyo() {
		return jinkyo;
	}

	public void setJinkyo(String jinkyo) {
		this.jinkyo = jinkyo;
	}

	public String getHyoshi() {
		return Hyoshi;
	}

	public void setHyoshi(String hyoshi) {
		Hyoshi = hyoshi;
	}

	public int getPower() {
		return power;
	}

	public void setPower(int power) {
		this.power = power;
	}
}

ErrorMan.java ← サブクラス

package dto;

public class ErrorMan extends SuperMan {

	private String miss;

	private int power;

	public ErrorMan() {
		super();
	}

	public String getMiss() {
		return miss;
	}

	public void setMiss(String miss) {
		this.miss = miss;
	}

	public int getPower() {
		return power;
	}

	public void setPower(int power) {
		this.power = power;
	}
}

TestSubInToSupser.java ← 実行クラス

package main;

import dto.ErrorMan;
import dto.IppMan;
import dto.Sub;
import dto.SuperMan;

public class TestSubInToSupser {

	private static int SUPERMAN_BORDERLINE = 100;
	private static int STARMAN_BORDERLINE = 60;

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		int power = (int)(Math.random() * 100) +1;
		int chance = (int)(Math.random() * 10) +1;
		SuperMan sp = null;


		if (chance == 10) {
			sp = takeIppManOrErrorMan(sp, power);
		} else {
			sp = takeSubManOrErrorMan(sp, power);
		}

		if (sp instanceof IppMan) {
			System.out.println("イップマン");
		} else if (sp instanceof Sub) {
			System.out.println("一般の人");
		} else if (sp instanceof ErrorMan) {
			System.out.println("エラーマンが...");
		}

	}

	public static SuperMan takeIppManOrErrorMan(SuperMan sp, int power) {

		if (STARMAN_BORDERLINE < power && power <= SUPERMAN_BORDERLINE) {
			sp = new IppMan();
		} else {
			sp = new ErrorMan();
		}
		return sp;
	}

	public static SuperMan takeSubManOrErrorMan(SuperMan sp, int power) {

		if (0 < power && power < STARMAN_BORDERLINE ) {
			sp = new Sub();
		} else {
			sp = new ErrorMan();
		}
		return sp;
	}

}
    

んで、実行。

f:id:ts0818:20190207202950p:plain

1回目の実行で出た。

f:id:ts0818:20190207203020p:plain

3回ぐらい実行して出た。

f:id:ts0818:20190207203049p:plain

20回ぐらい実行して出た。

f:id:ts0818:20190207203120p:plain

スーパクラスに、スーパクラスを継承したサブクラスたちを入れとくことができると。

そして、そのスーパークラスを instanceof すると、サブクラスたちを判定できるんだと。ポリモーフィズムっちゅうやつですかね。

一回しか実行したくないメソッドの戻り値の型が、複数ある場合でも、戻り値の型が共通のスーパークラスを継承していてくれれば、メソッドの戻り値を受け取る変数として共通のスーパークラスで受け取れるということですね、つまり、メソッドの実行が1回で済むと。あくまで、そういう設計になってるクラスの場合に限りますが。

 

■ 今日の教訓

共通のスーパークラスを継承したサブクラスが用意されている場合は、共通のスーパークラスの変数で受け取れる。その後で、instanceof して、どのサブクラスを受け取れたか確認すればOK。

 

何にせよ、昨日よりは1mmぐらい成長したと思い込んでみますか...。

今回はこのへんで。