はじめに
この章では、インスタンス化を行うことができる具象クラス、抽象メソッドを定義することができる抽象クラス、クラスにおいて仕様の役割を持つインターフェースについて、それぞれの特徴と定義の方法を学習します。
目次
- 抽象クラス
- 抽象クラスの定義
- 抽象クラスの実装
- 抽象クラスのポリモーフィズム
- インターフェース
- インターフェースの定義
- インターフェースの実装
- インターフェースのポリモーフィズム
- 章のまとめ
目標
抽象クラスとインターフェースについて理解すること。
抽象クラス
抽象クラスとは、他のクラスにより、継承されることを前提に定義されたクラスです。そのため、抽象クラスはインスタンス化することができません。

抽象クラスは、クラスの設計をおこなう際に、まだ処理内容が明確に決まってない場合に、概要だけを抽象メソッドとして定義し、そのクラスを継承したサブクラス内で詳細な処理を定義する設計手法です。
抽象クラスの定義

抽象クラスを定義するためには、クラスの宣言にabstractキーワードを付けます。abstractキーワードをつけることにより、定義が完結していないことを示します。メソッド内の処理定義が無く、末尾にセミコロン( ; )をつけたメソッドを抽象メソッドといいます。抽象メソッドはメソッドの宣言にabstractキーワードを付けます。
一方、メソッド内に、処理が定義されているメソッドを具象メソッド(通常のメソッド)といいます。抽象クラス内では、抽象メソッドや具象メソッドのどちらでも定義可能です。
尚、抽象クラス(abstractキーワードが付与されたクラス)は定義が不完全な為、newでオブジェクトを作成(インスタンス化)することはできません。
抽象クラスの定義例
以下は抽象クラスと抽象メソッドの例です。
抽象メソッドを持たない抽象クラスの定義例//抽象クラス
abstract class Sample01{
//具象メソッド
public void A(){
System.out.println("A method");
}
}抽象メソッドと具象メソッドを含む抽象クラスの定義例//抽象クラス
abstract class Sample01{
//具象メソッド
public void A(){
System.out.println("A method");
}
//抽象メソッド
abstract void B();
}抽象メソッドのみの抽象クラスの定義例//抽象クラス
abstract class Sample01{
//抽象メソッド
abstract void B();
}何もメソッドが定義していない抽象クラスの定義例//抽象クラス
abstract class Sample01{
}
抽象クラスの実装
抽象クラスは、サブクラスで継承(extends)し、実装して利用します。
※抽象クラスのメソッドをオーバーライドし、具体的な処理を記述することを実装するといいます。
以下、実装する際の構文です。

抽象メソッドは不完全なので、スーパークラスで定義されている全ての抽象メソッドはサブクラスで実装しなければなりません。もし、サブクラスで一部のメソッドを実装しなかった場合、コンパイルエラーになります。
例題(抽象クラスの利用①)
以下サブクラスで実装している例です。
抽象クラスおよびサブクラスを定義し、実行結果を確認してください。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス名 | Greeting |
package chapter10; |
抽象クラスを作成するときはabstractキーワードを使用します。またメソッドに関しても抽象メソッドという形式で書きます。
尚、abstractキーワードはアクセス修飾子の前に書いても良いです。
package chapter10; |
抽象クラスを継承したサブクラスでは、必ずabstractキーワードが付与されているメソッドをオーバーライド(実装)します。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス名 | JapaneseGreeting |
| 継承 | Greeting |
package chapter10; |
サブクラスで抽象メソッドをオーバーライド(実装)しないとコンパイルエラーになります。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス名 | GreetingExec |
package chapter10; |
コンパイル例:> javac chapter10¥Greeting.java
> javac chapter10¥JapaneseGreeting.java
> javac chapter10¥GreetingExec.java
実行例:> java chapter10.chapter10¥GreetingExec
言語:Japanese
挨拶:こんにちは

Greetingクラスがスーパークラスであり、抽象クラスとして定義されています。JapaneseGreetingクラスがGreetingクラスを継承し、抽象メソッドをオーバーライド(実装)しているサブクラスです。GreetingExecクラスは実行するためのクラスで、
Greetingクラスがスーパークラスであり、抽象クラスとして定義されています。JapaneseGreetingクラスをインスタンス化し、生成されたJapaneseGreetingオブジェクトをサブクラス型(JapaneseGreeting型)の変数jgへ代入し、jg.language()、jg.message()で実行しています。
例題(抽象クラスの利用②)
以下も、サブクラスで実装している例です。
抽象クラスおよびサブクラスを定義し、実行結果を確認してください。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス名 | Transport |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス名 | Car |
| 継承 | Transport |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス名 | Bass |
| 継承 | Transport |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス名 | TransportExec |
package chapter10; |
コンパイル例:> javac chapter10¥Transport.java
> javac chapter10¥Car.java
> javac chapter10¥Bass.java
> javac chapter10¥TransportExec.java
実行例:> java chapter10.TransportExec
Car:スピード : 100
止まります。
Bass:スピード : 50
止まります。
上記、イメージとしては以下のようになります。

Car型の変数cはCarオブジェクトを参照しています。Bass型の変数bはBassオブジェクトを参照しています。
c.run();とb.run();と実行することで、サブクラスでオーバーライドしたrun()メソッドを実行しています。
抽象クラスのポリモーフィズム
抽象クラスはオブジェクトを作成することはできません。しかし、変数として利用することはできます。変数にはサブクラスのオブジェクトの参照を代入することが可能です。

抽象クラスを変数として利用すると、ポリモーフィズムを実現することができます。
例題(抽象クラスのポリモーフィズム)
以下は、抽象クラスでのポリモーフィズムを実現しているプログラムの書き方です。
先ほど作成しました、TransportExecクラスを以下へ修正し、実行結果を確認してみましょう
※Transportクラス、Carクラス、Bassクラスはそのまま利用します。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス名 | TransportExec |
package chapter10; |
コンパイル例:> javac abstractInterfacePk¥TransportExec.java
実行例:> java abstractInterfacePk.TransportExec
Car:スピード : 100
止まります。
Bass:スピード : 50
止まります。
上記、イメージとしては以下のようになります。

変数tがTransport型(スーパクラス型)で、参照しているオブジェクトがCarオブジェクトやBassオブジェクト(サブクラス)になっています。(参照型のキャスト) またrun()メソッドがオーバーライドされており、ポリモーフィズムを実現しています。
インターフェース
インターフェースとは、操作方法を統一するために操作のアクセスの手段のみを定義するプログラム部品のことです。
- 例)銀行のATM
銀行が異なっていてもATMの操作方法は統一されている
(振込、預け入れ、払い出し)

インターフェースはクラスではありませんが、クラスに準じる存在です。先ほど出てきました抽象クラスと定義方法や使い方は似ていますが。クラスでは継承というところをインターフェースでは、実装といいます。インターフェースを実装するクラスは、インターフェースが定義している抽象メソッドをオーバーライドしなければなりません。
抽象クラスと違う点は、インターフェースはクラスではないので、継承関係を考慮しなくても良いということです。
インターフェースの利用方法として、主に以下の2つがあります。
単一継承の欠点を補う利用方法公開メソッドを明確にする手段としての利用方法
単一継承の欠点を補う利用方法
Java言語では、クラスが継承できるスーパークラスは1つだけです。これを単一継承といいます。例えば、次の図は同時に2つのクラスをスーパークラスにしてサブクラスを作成しようとしていますが、Java言語ではこのような多重継承は許されません。

しかし、インターフェースはクラスではないので、インターフェースを実装することで、複数のクラスを継承するのと同じような効果を上げることができます。次の図は継承の代わりにインターフェースを実装し、利用しているケースを示しています。なお、図のようにインターフェースの実装は、点線で表す決まりになっていることも覚えておいてください。

インターフェースは特定の機能を実現するために利用します。特定の機能の実現を考え、そのために必要なメソッドを抽象メソッドとして羅列しただけのものが、インターフェースです。インターフェースを実装したクラスは、インターフェースで定義されている特定の機能を自身のクラスへ付加するために使います。
公開メソッドを明確にする手段としての利用方法
インターフェースは特定の機能を実現するために必要な定数や抽象メソッドの集まりです。また、インターフェースで定義する定数や抽象メソッドは、全てpublicなメンバだけから構成されます。
一方、クラスにおいてpublicなメンバは外部に公開するメソッドを意味し、インターフェースを確認するたけで、クラスの機能がわかります。そこで、クラスでpublicにするメソッドを全てインターフェースとして定義し、それを実装してクラスを作成することが考えられます。この場合、インターフェースを見るだけで利用できるメソッドが分かるので、文字通り、クラスの外観とのインターフェースを定義する、ということになります。

このような使い方は、グループでひとつのシステムを開発する際に、システムに対する理解を共有するために利用されます。
インターフェースの定義
インターフェースはクラスに準じる存在で次のように、定数とメソッドだけを定義できます。インターフェースはinterfaceというキーワードを使って定義します。

インターフェースには定数と抽象メソッドだけを定義できる- クラス宣言には
abstractが自動的にコンパイラによって付加される - 定数には
public static finalが自動的にコンパイラによって付加される - メソッドには
public abstractが自動的にコンパイラによって付加される - インターフェースファイル名も
拡張子はjavaである extendsで他の複数のインターフェースを拡張できる
インターフェースのコンパイル
ここではWithdrawという名前のインターフェースを参考に解説します。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース名 | Withdraw |
package chapter10; |
上記のように、インターフェースには定数と抽象メソッドだけを定義します。
※Java SE8からはdefaultキーワードを利用すると、具象メソッドを定義することが可能になっています。
尚、以下のように定義することも可能です。
package chapter10; |
上記のインターフェースをコンパイルすると以下のようになります。
package chapter10; |
上記をコンパイルすると、自動的にpublicアクセスとみなされるので、定義の中でpublicをつける必要はありません。また、staticやfinal、abstractも、コンパイラが自動的に付加してくれるので、定数やメソッドにプログラマ自身が付加する必要はありません(付けても間違えではないです。)
static
statcをつけたメンバ変数やメソッドは、クラス変数、クラスメソッドといい、クラスに一つしかない固有なものです。インスタンス変数やインスタンスメソッドがオブジェクトの中に取り込まれて、各オブジェクトごとに存在するのに対して、クラス変数、クラスメソッドはクラス定義の中に一つだけ存在します。クラス変数、クラスメソッドは静的メンバと呼ばれ、クラスから作成された全てのオブジェクトで共有されます。したがって、クラスから作成されたオブジェクトは静的メンバに自由にアクセスできます。
final
finalは「変更できない」という意味の修飾子です。クラス、メソッド、変数の宣言時に使うことができます。
それぞれの効果は以下です。
| 対象 | 用例 | 効果 |
|---|---|---|
| クラス | final class Foo{} | 継承できない |
| メソッド | final int addTashizan(){} | サブクラスでオーバーライドできない |
| 変数 | final int MAX = 1000; | 初期化時に代入した値を後から変更できない |
finalな変数は宣言時に必ず値を代入しなければなりません。代入した値を変更できないので、その数値の代わりに使うことができます。なお、変数をfinalにして定数として使う時は、大文字を使うという慣例があります。
extendsを伴うインターフェースの定義
インターフェースを定義する際、他のインターフェースを継承(extends)して作成することも可能です。
以下、インターフェースAはインターフェースXとインターフェースYを継承して、定義しています。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース名 | X |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース名 | Y |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース名 | A |
| 継承 | X、Y |
package chapter10; |
※インターフェースは多重継承することが可能です。

尚、クラスへ実装する場合は、全てのインターフェースで定義されている抽象メソッドをオーバーライドしなければなりません。(次の項目の「インターフェースの実装」を参考にして下さい)
インターフェースの実装
インターフェースを実装するときはimplementsキーワードを利用します。そしてインターフェースで定義しているメソッドをオーバーライドします。正しく利用しないとコンパイルエラーになります。

implementsキーワードを使ってインターフェースを実装する- 一度に
複数のインターフェースを実装できる - クラスの
継承(extends)と併用できる
例題(インターフェースの実装)
以下はインターフェースの実装する例です。
コーディングし、実行結果を確認してみましょう。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース | Tools |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース | Var |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス | Parent |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス | Child |
| 継承 | Parent |
| 実装 | Tools , Var |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス | ChildExec |
package chapter10; |
コンパイル例:> javac chapter10¥Tools.java
> javac chapter10¥Var.java
> javac chapter10¥Parent.java
> javac chapter10¥Child.java
> javac chapter10¥ChildExec.java
実行例:> java chapter10.ChildExec
500
100
この例は一つのクラスを継承し、2つのインターフェースを実装(imprements)します。インターフェースのメソッドは抽象メソッドですから、実装するChildクラスでオーバーライドします。オーバーライドしない場合には、Childクラスを抽象クラスにする必要があります。
メソッドは自動的にpublicになるので、インターフェースの抽象メソッドにpublicが付いていなくても、実装するときにはpublicをつける必要があります。また、アクセス修飾子をpublicより厳しくすると、オーバーライドの規約からコンパイルエラーになります。
インターフェースのポリモーフィズム
インターフェースも変数として利用することはできます。変数にはインターフェースを実装したクラスのオブジェクトの参照を代入することが可能です。
インターフェースも抽象クラスと同様に変数として利用すると、ポリモーフィズムを実現することができます。
例題(インターフェースのポリモーフィズム①)
以下は、インターフェースのポリモーフィズムを実現しているプログラムの書き方です。
コーディングして、実行結果を確認してみましょう。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース | Responsible |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス | Member |
| 実装 | Responsible |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス | MenberExec |
package chapter10; |
コンパイル例:> javac chapter10¥Responsible.java
> javac chapter10¥Member.java
> javac chapter10¥MenberExec.java
実行例:> java chapter10.MenberExec
Member ver1.0
ALJ会員のクラス
MenberExecクラスの「Responsible res = new Member(“ALJ”,123);」でMemberオブジェクトを作成し、Responsible型(インターフェース型)の変数「res」へ代入してます。そしてMemberクラスはResponsibleインターフェースを実装しており、「System.out.println(res.info());」と「System.out.println(res.exp());」でインターフェースで定義されているメソッドの実行結果を出力しています。「System.out.println(res.getName());」のres.getName()メソッドを実行するとコンパイルエラーになります。
例題(インターフェースのポリモーフィズム②)
以下も、インターフェースのポリモーフィズムを実現しているプログラムの書き方です。
(インターフェースAは、インターフェースXとインターフェースYを継承して定義している例です。)

コーディングし、実行結果を確認して下さい。
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース名 | X |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース名 | Y |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| インターフェース名 | A |
| 継承 | X、Y |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス | G |
| 実装 | A |
package chapter10; |
| 項目 | 名前 |
|---|---|
| プロジェクト | alj_study |
| パッケージ | chapter10 |
| クラス | InterFaceExec |
package chapter10; |
コンパイル例:> javac chapter10¥X.java
> javac chapter10¥Y.java
> javac chapter10¥A.java
> javac chapter10¥G.java
> javac chapter10¥InterFaceExec.java
実行例:> java chapter10.InterFaceExec
dispA()メソッドの実行
dispX()メソッドの実行
dispY()メソッドの実行
章のまとめ
以下の要点をしっかり理解してから次の章へ進んでください。
抽象クラス
抽象クラスとは、クラスを設計するときに、処理内容が明確に決まってないメソッドがある場合、概要だけを定義したメソッドを用意し、後にそのクラスを継承し、サブクラス内で詳細な処理を定義する設計手法である
抽象クラスの定義
- クラスの宣言に
abstractキーワードを指定すると抽象クラスになる 処理定義が無く、末尾にセミコロン( ; )をつけたメソッドを抽象メソッドという抽象メソッドを定義するときはabstractキーワードを指定する抽象クラスはnewでオブジェクトを作成できない抽象メソッドの詳細な処理内容は、サブクラスでオーバーライドして定義する
抽象クラスの実装
抽象クラスは継承(extends)し、抽象メソッドをオーバーライドする抽象クラスのメソッドをオーバーライドして具体的な処理を記述することを実装という- @から始まる記述は、
アノテーションといい、コンパイラに対しての命令を示す - @Overrideはコンパイラに対して、
オーバライドしていることを明示的に示している 全ての抽象メソッドをオーバーライドしない場合は、サブクラスは抽象クラスにしなければならない
抽象クラスのポリモーフィズム
抽象クラスはインスタンス化ができないが、変数として利用することは可能- 抽象クラスが変数として利用されると、
ポリモーフィズムとして利用されていることとなる
インターフェース
インターフェースとは、操作方法を統一するために操作のアクセスの手段のみを定義するプログラム部品のことインターフェースはクラスでは無いので、継承関係を考慮しなくても良い単一継承の欠点を補う利用方法と公開メソッドを明確にする手段としての利用方法があるクラスが継承できるスーパークラスの数は、1つだけである(
単一継承という)インターフェースは、クラスでは無いので、あたかも複数のクラスを継承するのと同じ効果を上げることができるインターフェースは、特定の機能を実現するために必要な定数や抽象メソッドの集まりであるインターフェースで定義する定数や抽象メソッドは、全てpublicなメンバで構成される- 外部に公開するメソッドを
全てインターフェースとして定義することで、クラスの利用者は実装されているインターフェースを確認すれば、クラスにどのような機能があるかを理解できる
インターフェース定義
インターフェースには定数と抽象メソッドのみ定義ができる- Java SE8からは
defaultキーワードを利用すると、具象メソッドを定義することが可能 - 定数には
public static finalが自動的に付加される - メソッドには
public abstractが自動的に付加される - インターフェースファイル名も拡張子は
.javaである extendsで他の複数のインターフェースを拡張できる
インターフェースの実装
implementsキーワードでインターフェースをクラスへ実装できる- 一度に
複数のインターフェースを実装できる - クラスの
継承(extends)と併用できる
インターフェースのポリモーフィズム
インターフェースは、変数として利用することは可能(インターフェース型)- インターフェースが変数として利用されると、
ポリモーフィズムとして利用されていることとなる