ぶろぐ

日記です

abstractとinterface


interfaceとabstract

あれ?同じじゃね?と風呂場で思ったので調べてみた。

  • interface
    • 動きを制限、インターフェースに定義したメソッド以外は実装できない
    • ポリモーフィズムを適用(寧ろ強制?)するために使う
    • 型になるよ!
  • abstract
    • 子供が必要、親子関係が生まれる
    • 単体でインスタンスできない
    • abstractメソッドを持つクラス
    • 継承を強制したいときに使うのかな?
    • ある意味では機能が足りない部分があるクラス

とりあえずinterfaceとabstractの違いを知りたくてコード叩いてみたから載せる

interface編

interfaceは、inplementするクラスのメソッドを制限して再利用性を高めるために使うものっぽい
interfaceは型として使える
Listはインターフェース、ArrayListはそれを実装したクラス
だからinterface分かってそうな人はこう書く

List<String> list = new ArrayList<String>();

interface分かってなさそうな人はこう書くはず(Java勉強しはじめのオレ)

ArrayList<String> list = new ArrayList<String>();

ぶっちゃけArrayListしか使わないならこれでいいけど、もしかしたらLinkedList使いたくなるかもしれないし、データはデータで考えを分けたい。これだとlistのデータを扱うときArrayListに依存するから気持ち悪い。

ポリモーフィズム

あと、オブジェクトに対する操作が限定されるので、Implementsしたクラスの使い方はどれも一緒。
なのでまとめて処理を行うとき、interfaceを使うと便利らしい

List<Hello> helloList = new ArrayList<Hello>();
helloList.add(new HelloJapan("こんにちは"));
helloList.add(new HelloEu("hello"));
helloList.add(new HelloOkinawa("はいさい"));

for(Hello hello : helloList) {
	hello.sayHello();
}

ポリモーフィズムの考えが適用されている。

以下コード
/**
 * HelloInterface
 */
public interface HelloInterface {
	
	public void sayHello();	
	// public String message; だとダメな理由って?
	// 分かった、単体でインスタンス化することがあるから、その時に困るからだ
	public String message = "hello";

}
/**
 * HelloInterface実装クラス
 */
public class HelloInpl implements HelloInterface {

	// HelloInterfaceで定義されているメソッドしか実装できない
	@Override
	public void sayHello() {
		System.out.println("hello");
		System.out.println(message);	
	}
}
/**
 * メインクラス
 */
public class Main {
	public static void main(String[] args) {
		HelloInpl hello = new HelloInpl();
		hello.sayHello();
	}
}

Abstract編

Abstractは、Abstractメソッドを持つクラス。
継承するクラスはAbstractメソッドを必ずオーバーライドしないといけない。
なんか作りかけのクラスって感じですな

/**
 * HelloAbstractクラス
 */
public abstract class HelloAbstract {
	// Abstractは変数初期化しなくていいんだ…
	public String message;
	public abstract void sayHello();
}
/**
 * HelloAbstractの具象クラス
 */
public class Hello extends HelloAbstract {

	@Override
	public void sayHello() {
		System.out.println("hello");
	}
	
	// メソッドを増やしてもOK!
	public void sayHelloWorld() {
		System.out.println("HelloWorld!!");
		return;
	}

}
public class Main extends Hello {

	public static void main(String[] args) {
		Hello hello = new Hello();
		hello.sayHello();
		hello.sayHelloWorld();
	}
}

まとめ

自由度 : Abstract >> Interface

  • Interfaceは自由を制限して再利用性を上げるための物
  • extendsは一つしかできない
  • implementsは複数OK
  • でもextendsしたクラスをextendsはできるんだよなー、多重継承禁止、でも継承したクラスの継承はOK。継承は一つづつやろうってことかな。
  • Abstractクラスはインスタンス化できない
  • Interfaceはインスタンス化できる。型として使う。

Abstractっていつ使うのか分かんない。
作りはしないけど、フレームワーク使うときにEclipse先輩に怒られて@overrideする感じ?
Template Methodパターンに答えがありそうな気がする、それ学ぼう。

戯言

実際作るとき、interfaceって非常に面倒くさい
パシ!と作ってリファクタリングの時に色々やる、ってやり方はまずいかなぁ
TDDがテストケースを書いてコーディングを始めるのように、interfaceを先に書いてクラス作る、とかあるのかな?