【Java】インターフェース

2018年1月5日

本稿はJavaのインターフェースの機能について説明します。

インターフェースとは抽象クラスと似ている部分もあるのですが、少し変わった特徴があります。

インターフェースは、抽象クラスが多重継承不可能なのに対し、多重継承が可能となります。

定義したインターフェースは、暗黙的にabstract classが付与されたクラスのようなものになります。

定義した変数は、暗黙的にpublic staticが付与された状態となります。よってオブジェクト化したときに変数は実体化されません。

定義したメソッドは、暗黙的にpublic abstractが付与された状態となります。

初心者の方はインターフェースのメリットがわからないという人が多いのですが、

複数の型を与えられるということになるので、それだけポリモーフィズムの特性を扱いやすくなるんですね。

これは結構メリットがあることなんです。

インターフェースの定義

インターフェースの定義は「interface インターフェース名」となります。

メソッドは明示的にpublic abstractとつけることもできますが省略しても、結果は変わりません。

メソッドの定義は「(public)(abstract) 戻り値 メソッド名」となります。

interface Chara{
	void move();
}

インターフェースの利用

インターフェースをクラスに実装したい場合は、「implements インターフェース名」と記述します。

インターフェースをクラスに多重実装したい場合は、「implements インターフェース名,インタンフェース名…」と記述します。

インターフェースを利用したサンプルです。

public class Test{
	public static void main(String[] args){
		Chara a = new Teki();
	}
}
interface Chara{
	void move();
}
class Teki implements Chara{
	public void move(){
		System.out.println("移動");
	}
}
実行結果

移動

インターフェースの継承

インターフェースはインターフェースに継承させることもできます。

継承したインターフェースは継承元のインターフェースの特徴をそのまま受け継ぎます。

インターフェースの継承は、「extends インターフェース名」と記述します。

多重継承する場合は、「extends インターフェース名,インターフェース名…」と記述します。

public class Test{
	public static void main(String[] args){
		Enemy teki = new Teki();
		teki.atk();
		teki.move();
	}
}
interface GameObject{
	void move();
}
interface Enemy extends GameObject{
	void atk();
}
class Teki implements Enemy{
	public void move(){
		System.out.println("移動");
	}
	public void atk(){
		System.out.println("攻撃");
	}
}
実行結果

攻撃
移動

インターフェースの変数

インターフェースに変数を定義すると、public staticが付与された変数になります。

なので、インスタンス化しなくてもアクセス可能になります。

public class Test{
	public static void main(String[] args){
		System.out.println(GameObject.hp);
	}
}
interface GameObject{
	int hp=100;
}
実行結果

100

インターフェースのdefaultメソッド

インターフェースには処理を行うメソッドも定義できます。

「default 戻り値 メソッド名」と定義しましょう。

このデフォルトメソッドは暗黙的にpublicとなります。

public class Test{
	public static void main(String[] args){
		GameObject g = new Teki();
		g.move();
	}
}
interface GameObject{
	default void move(){
		System.out.println("移動");
	}
}
class Teki implements GameObject{
	
}
実行結果

移動

デフォルトメソッドの多重継承

多重継承できるということは、同じデフォルトメソッドを継承できるわけですが、どちらか特定できない場合はコンパイルエラーとなります。

デフォルトメソッドをオーバーライドすればちゃんと動作させることはできます。

また、実装メソッド内でどちらのメソッドかを呼び出す場合は「呼び出したい型.super.メソッド名」で可能です。

public class Test{
	public static void main(String[] args){
		Player g = new Chara();
		g.move();
	}
}
interface Player{
	default void move(){
		System.out.println("キャラ移動");
	}
}
interface Enemy{
	default void move(){
		System.out.println("敵移動");
	}
}
class Chara implements Player,Enemy{
	public void move(){
		Player.super.move();
	}
}
実行結果

キャラ移動

インターフェースでポリモーフィズムの特性を活用

最後にインターフェースを利用した少し複雑なプログラムを作成してみましょう。

複数の独自キャラをCharaクラスから継承させて設計し、時間停止能力を使用できるキャラにはインターフェースを実装し、独自の能力名を表示する処理を作成してみました。

instanceofを途中で使用しているため、あまりすっきりする例ではありませんが興味がある方は内容を確認してみてください。

public class Test{
	public static void main(String[] args){
		Chara[] chList = new Chara[]{
			new YellowGirl()
			,new BlackGirl()
			,new Latifa()
			,new Kyuketsuki()
			,new Student()
		};
		for ( Chara ch : chList ) {
			System.out.println(ch.name);
			ch.skill();
			if ( ch instanceof TimeStopChara ) {
				TimeStopChara tch = (TimeStopChara)ch;
				tch.timeStopSkill();
			}
			System.out.println();
		}
	}
}
interface TimeStopChara{
	void timeStopSkill();
}
abstract class Chara{
	String name;
	Chara(String name){
		this.name = name;
	}
	abstract void skill();
}
class YellowGirl extends Chara{
	YellowGirl(){
		super("マ〇");
	}
	void skill(){
		System.out.println(" ティ〇・フィナー〇");
	}
}
class BlackGirl extends Chara implements TimeStopChara{
	BlackGirl(){
		super("ほむ〇");
	}
	void skill(){
		System.out.println(" 銃火器の使用");
	}
	public void timeStopSkill(){
		System.out.println(" 時間停止魔法");
	}
}
class Latifa extends Chara{
	Latifa(){
		super("ラティファ");
	}
	void skill(){
		System.out.println(" リオ・ソル");
	}
}
class Kyuketsuki extends Chara implements TimeStopChara{
	Kyuketsuki(){
		super("D〇O");
	}
	void skill(){
		System.out.println(" むだ");
	}
	public void timeStopSkill(){
		System.out.println(" 〇・ワ―〇〇");
	}
}
class Student extends Chara implements TimeStopChara{
	Student(){
		super("〇〇郎");
	}
	void skill(){
		System.out.println(" おら");
	}
	public void timeStopSkill(){
		System.out.println(" ス〇ー〇〇チナ・ザ・〇〇ルド");
	}
}
実行結果

マ〇
 ティ〇・フィナー〇

ほむ〇
 銃火器の使用
 時間停止魔法

ラティファ
 リオ・ソル

D〇O
 むだ
 〇・ワ―〇〇

○○郎
 おら
 ス〇ー〇〇チナ・ザ・〇〇ルド