Javaの使い方メモ(Interface versus Abstract Class)

たまたま読んだ記事が、ためになったのでざっくり訳してみることにした。
こちらの記事 → Java: Interface versus Abstract Class

<補足>~~~~~~~~
Interfaceの使い方とか、基本的なところはこちらのサイトがわかりやすかった

(参考) あぷり部屋 - Java入門講座(インターフェイスについて理解しよう!)
(参考) interfaceについて本気出して考えてみた – 都元ダイスケ IT-PRESS
(参考) Java: Are objects of the same type as the interface implemented?
~~~~~~~~~~~~

ここから先、翻訳内容です。


What’s the difference between an interface and an abstract class in Java?
interfaceと抽象クラスの違いは?

まずは、それぞれの定義をざっくり確認してみる。そのうえで違いを確認してみよう!

abstractなメソッドを持つクラスは、abstractと宣言しないといけない。abstractなメソッドというのは、「メソッドを定義するが、具体的な処理内容を記述しない」といった形のメソッド。

When to use abstract methods in Java?
抽象メソッドのつかいどころ。

「なんで抽象メソッドをつかいたいって思うか?」、ってことを以下のExampleで考えてみる。

/* the Figure class must be declared as abstract 
   because it contains an abstract method  */

public abstract class Figure
{
	/* because this is an abstract method the 
	   body will be blank  */
	public abstract float getArea();	
}

public class Circle extends Figure
{
	private float radius;

	public float getArea()
	{
		return (3.14 * (radius * 2)); 	
	}
}

public class Rectangle extends Figure
{
	private float length, width;

	public float getArea(Figure other)
	{
		return length * width;
	}
}

上記では、抽象メソッドgetArea()が定義されています。なので、Figureクラスは抽象メソッドを持っていることになり、abstractと宣言しないといけない。

Figureクラスを継承したCircleクラス、Rectangleクラスが定義されており、それぞれのクラスにはgetAreaメソッドが定義されています。

ここでのポイントは、「なぜ、Figureクラスの中でgetAreaメソッドを抽象メソッドとして定義したか?」ということ。getAreaメソッドでは、図形の面積を計算しています。

Figureクラスの中では、特定の図形を指定していません。そのため、Figureクラスの中ではgetAreaメソッドに具体的な計算内容を定義していません(定義できない)。つまり、これが、Figureクラスの中ではgetAreaメソッドを抽象クラスとして定義している理由ですね。

Figureクラスを継承する場合、以下の2パターンが考えられる。
・Figureクラスを継承したサブクラスでgetAreaメソッドを実装(オーバーライド)する。
・Figureクラスを継承したサブクラスでgetAreaメソッドを実装(オーバーライド)しない場合、そのサブクラスは抽象クラスとして宣言する。

A non abstract class is called a concrete class
抽象クラスでないものは、具象クラスという。

ということをふまえて、次に、「Interfaceって何か、interfaceと抽象クラスの違いは?」を考えてみる。

Java interface versus abstract class
Interface vs 抽象クラス

Interfaceなクラスではありません。ってところが、抽象クラスとの違いです。
Interfaceは、ほかのクラスに継承されて利用されるtype(型?)になります。

Interfaceを継承するクラスは、以下の2つの条件を満たす必要があります。
・クラスを定義するときに、”implements Interface_Name“といった形で、定義する必要があります。
・クラスの中で、Interfaceで定義されているすべてのメソッドを実装しておく必要があります。

以下のような”Dog”というInterfaceがあった場合に、

public interface Dog
{
    public boolean Barks();
    public boolean isGoldenRetriever();
}

このInterfaceを継承したクラスは、以下のような感じになる。

public class SomeClass implements Dog
{
    public boolean Barks{
    // method definition here
    }

    public boolean isGoldenRetriever{
    // method definition here
    }
}

ここまでの内容で、Interfaceと抽象クラスについて、基本的なことを理解できたと思います。というわけで、それぞれの違いについて見ていきたいと思います。

Abstract classes and inheritance
抽象クラスと継承

(1)抽象クラスは、ほかのクラスに継承されるものになります。あるクラスが継承されるということは、互いのクラスに強い関連性(依存関係?)が生じるということになります。

たとえば、抽象クラスとしてCanineクラスが定義されているとします。Canineクラスを継承したクラス(DogとかWolfクラス)は、Canineファミリーに所属すべきです。「すべき」ということは、開発者がメンテナンス・維持管理していく、ってことになる。

それに対しInterfaceの場合、Interface本体と、「InterfaceをImplementしたクラス」との関係は強くない。
たとえば、Houseというクラスがあったとします。Houseクラスは、AirConditioningというInterfaceをImplementしているとします。この場合、HouseにAirConditioning(空調設備)があるかどうかはそれほど強い関係性ではありません。

逆に「Houseクラスを継承したApartmentクラスと、Houseクラス」といった関係性のほうがはるかに強いつながりを持っています。
なぜかというと、ApartmentはHouseの中の1つに属していることから関連が強いわけです。そのため、クラスの継承をつかってきっちり定義するべきです。この点がInterfaceとの違いになってきます。

まとめると、
抽象クラスとそれを継承したクラスの間に、つよい関係性が考えられる、という場合、「抽象クラスをつかうべき」です。抽象クラスは、”継承”により、クラス間が密接につながります。つまり関係性が強くなる。
それに対し、Interfaceの場合、Interfaceと、それをImplementしたクラスの間に、つよい関係性は必要ありません。

Interfaces are a good substitute for multiple inheritance
Interfaceは、多重継承の代わりになる。

(2)Javaは多重継承を許可していません。Javaでは、クラスは1つのクラスしか継承できません。抽象クラスであろうがそうでなかろうが、継承できるのは1つだけです。
ですが、Interfaceは複数Implementできます。そのため、多重継承の代替になりえます。

抽象クラスとInterfaceの主な違いの1つとしては、「Javaのクラスは、抽象クラスを1つだけしか継承できないが、Interfaceは複数Implementできる」、と言えます。

Abstract classes can have some implementation code
抽象クラスは、実装コードを持てる。

(3)抽象クラスは、メソッドに処理手順を書き込めます。抽象クラスは、具体的な処理を記載したメソッドを持つことができます。また、抽象クラスは、コンストラクタ・インスタンス変数も持つことができます。
ですが、Interfaceはメソッドに処理手順を書き込めません。メソッドの名前だけ定義できます。InterfaceをImplementするクラスは、Interfaceで定義されているメソッドについて、すべて実装する必要があります。

When to use abstract class and interface in Java
抽象クラス、Interfaceのつかいどころ。

抽象クラス、Interfaceをつかうときのガイドラインを以下に示します。

1.次のように考えているなら、抽象クラスが適している。
「共通のBaseとなるクラスを用意して、それを継承したクラスを使う」といった形で、”継承”を使っていこう!

2.Publicな使い方をしたくないなら、抽象クラスをつかうのがよい。Interfaceで定義するメソッドはPublicでないといけない。

3.将来的にメソッドの追加が予想される場合、抽象クラスを使うほうがよい。Interfaceにメソッドを追加すると、そのInterfaceをImplementしているクラスすべてに、メソッド追加しないといけなくなる。おおさわぎになるかも!?

4.さしあたり、APIに変更が入らないという場合、Interfaceをつかうのがよい。

5.多重継承のようなことを行いたいと思っている場合、Interfaceを使うのがよい。複数のInterfaceをImplementすることができる。

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s