ここではinterfaceと聞いてもまったくピンとこない。
abstractとinterfaceって何?interfaceとabstractの違いは?と混乱している人に参考になる程度で書いています。
私はJavaを勉強して数ヶ月の初心者なので、同じ初心者の方にわかりやすく伝わればと思っています。
(調べだすと難しくて、量も多くて後半力尽きだします。)
interface (インターフェース) とは
interfaceとはクラスから型だけを取り出したもので、内容が未定のメソッド(抽象メソッド)と定数を扱えます。
初心者にはまだ想像もつきませんが、詳細は決まってないけど大枠(型)だけ作ってしまおうという時にインターフェースを使うようです。
例:音楽を再生するコードを書くけど、まだ使う楽器決めてない、という時にplay()だけinterfaceで作っておく。後から、play()を実装した楽器のクラスを作れる。
インターフェースの特徴
- インターフェイスはインスタンス化することができない。
- インターフェイスは定数と抽象メソッドのみ定義できる。(defaultも可能になった)
- インターフェイスに定義した変数は「public static final」が自動でつく(定数となる)。
- インターフェイスのメソッドには、「public abstract」が自動でつく。
- インターフェイスを実装したクラスはインターフェイスにあるメソッドを必ず実装する。
- インターフェイスは複数実装できる。(多重継承)
- インターフェイスは、「implements」句を使用して別のクラスに実装できる。
インターフェースの宣言方法
インターフェースの宣言方法は下記のようになります。
アクセス修飾子 interface インターフェース名
実際に書いてみると下記のようになります。
public interface Instruments{
// any code
}
interfaceのアクセス修飾子は基本的にpublicです。(補完して使用するため)
※修飾子にprotectedとprivateは使用できません。デフォルトは可能。
interfaceのメソッド (抽象メソッド)の宣言
public interface Instruments{
void play();
//または public abstract void play();
}
「インターフェースに宣言されたメソッドは自動的にpublic かつ abstract になる」というルールがあります。そのためvoid play();と書いても自動的にpublic abstract void play();として扱われます。最近の傾向としては暗黙的修飾子(勝手にそうなる)は省略して書くようです。
※ちなみにinterfaceは抽象メソッドがなくてもなりたちます。定数だけでも可能です。逆もしかりで抽象メソッドだけでも成り立ちます。
interfaceの定数の宣言
public interface Instruments{
double pi = 3.14;
または public static final double pi = 3.14;
}
interfaceではフィールドでは定数のみ扱えます。変数と違い、いちど値を決めたら変更できません。そのためinterfaceでフィールドを宣言すると、「public static final」となります。static double pi のように書いても「public static final」として扱われます。
インターフェースの実装方法 (実現)
インターフェースの実装方法は下記のようになります。
アクセス修飾子 class クラス名 implements インターフェース名
実際に書いてみると下記のようになります。
public class Trumpet implements Instruments{
//any code
}
インターフェースに抽象メソッドがあれば、必ず実装しなければなりません。
public class Trumpet implements Instruments{
public void play(){
//any code
}
}
}
アクセス修飾子はpublicになります。
インターフェースの多重実現 (継承)
インターフェースは複数クラスに実現できます。
アクセス修飾子 class クラス名 implements 親インターフェース名1,
親インターフェース名2,…{
///
}
言葉で書くとよくわからないですね。
実際に書いてみると下記のようになります。
public class Piano implements Instruments, Character{
// any code
}
擬人化したピアノみたいなクラスができました。
3つ以上でも実現可能です。
※これもインターフェースによる継承と呼ばれたりしていて次の継承とごちゃごちゃして混乱します。implementsによる継承は継承元がインターフェース、継承先がクラスとなります。
インターフェースの継承
インターフェイスもクラス同様、継承できます。
public interface Quartet extends Instruments{
void talk();
void watch();
//さらに、Instrumentsインターフェースからplay()を継承
}
オーバーライドして処理の内容を確定しているわけではないので、継承したメソッドも抽象メソッドとなります。
こちらも複数継承可能です。
クラスにはできないインターフェースの特権、それが多重継承です。
※extendsによる継承は継承元がインターフェース、継承先もインターフェースとなります。
同種(クラス同士、インターフェース同士)の場合はextendsを使うと覚える。
2つとも(implementsとextends)書く
implementsとextends両方を使ってクラス定義ができます。
アクセス修飾子 class クラス名 extends 親クラス implements 親インターフェース1, 親インターフェース2,…{
// any code
}
interface と abstract の違い
はじめinterfaceとabstract のことを全く違うものだと思って大混乱していました。
しかしinterface (インターフェース) とabstract (アブストラクト) は抽象メソッドを扱える仲間のようなものです。
しかもinterfaceにabstract修飾子のabstractをつけることもできてしまうのです。けれど、もともとinterfaceでは抽象メソッドを扱うことができるので書く必要はないです。
大きな違いとしてはinterfaceは多重継承ができる、abstractは多重継承ははできません。
またabstractは具体的な処理(具象メソッド)を書くことができます。(Java8からはinterfaceでもデフォルトメソッドで具体的な処理もできる)
interface とabstractの使い分け
interfaceとabstract の使い分けはどちらもあいまいな枠決めに使われますが、初心者としては大規模なものはインターフェースを使えばいいと思っておけばよさそうです。
デフォルトメソッド
インターフェースではデフォルトメソッドが実装できるようになりました。(Java8以降)
default 戻り値 メソッド名(引数){
// 処理のデフォルト実装
}
継承先でオーバーライドされなかった場合デフォルト実装として自動でオーバーライドとみなされる。