インタフェース 〜1番抽象的な親クラス〜
〈インターフェース〉
継承されたクラスは元をたどっていくとどんどん抽象的になっていく
ex. Goblinクラス int hp; attack( ){ 中身確定};
int mp; run( ){中身確定};
↓
(抽象メソッドが増える)
WalkMonsterクラス int hp; abstract attack( ); 中身は未定
int mp; run( ){中身確定};
↓
(抽象メソッドばかりになる)
Monsterクラス int hp; abstract attack( ); 中身は未定
int mp; abstract run( ); 中身は未定
↓
(フィールドや抽象メソッドが減り始める)
BattleCharacterクラス int hp; abstract run( ); int mp;とattack( );は消失
↓
(抽象メソッドだけになる)
Characterクラス abstract run( ); int hp;は消失
Javaでは特に抽象度の高いクラス(上のCharacterクラスのようなクラス)を
インターフェースとして特別扱いする
〈インターフェースの条件〉
① すべてのメソッドは抽象メソッド(abstractつきメソッド)である
② 基本的にフィールドを1つも持たない(フィールドがある方がより具体的になっていく)
また、インターフェースで宣言するとメソッドは自動的にpublicかつabstractになるので、わざわざ記述しなくてもOK!
public abstract class Character{
public abstract void run( );
}
↓
public interface Character{
void run( );
}
インターフェースとは、、、
あまりに曖昧すぎて特別扱いされた抽象クラスのこと
※ インターフェースは基本的に「普通のフィールド」を持たないが、
「static final」がついたフィールド(定数フィールド)だけは宣言が許される。
static(静的)…クラスに直接値がついている
(インスタンス生成時に記述しなくてもその値が自動で入る)
final….代入した値を変えることが出来なくなる制限
そもそもインターフェースのフィールドはstatic finalではないと無理なので、わざわざ記述しなくてもOK!
public interface Circle{
doble PI=3.14; ←static final扱い
}
〈なぜ「インターフェース」という名前なのか?〉
インタフェースとは接点という意味 ex お店と客の接点→メニュー
抽象メソッドしかないということは、見方を変えるとメソッドのタイトルしか記述されてないということ(メニュー表のような感じ)
インタフェースがメニューだとすると、
そのインタフェースを継承したクラスはそのメニュー内容を実行してくれるお店そのもの(本体)
インタフェースを継承した子クラスを定義する場合だけは特別に
extendsではなく、implementsを使う
インタフェースから子クラスを定義することを「実装する」という
インタフェースの中身は抽象メソッドしかないので、子クラス側でそれぞれをオーバーライド(上書き)しなければならない。
「実装する」とは、
親インタフェースで未定だった各メソッドの中身をオーバーライド(確定)していく作業
・ 1つのインタフェースから、何個もクラスを作成(継承)し、
フィールドやメソッドの内容をそれぞれのクラスで違う内容で実装しても大丈夫
・ しかし、最低でもインタフェースで定められている抽象メソッドは全てオーバーライド(上書き)をして中身を実装している必要がある
↓
この2つの点をインタフェース側の視点から考えてみると、、、
〈インタフェースの効果〉
① インタフェースをimplements(継承)する複数の子クラス達に、共通のメソッド群を実装するように強制できる
② 子クラスがこのインタフェースを実装していれば、少なくともインタフェースが定めたメソッドは持っていることが保証される
〈なぜインタフェースだけ特別にその名前にしているのか?〉
インタフェース…内部実装(メソッドの中身)を一切定めていないクラス
↓
このクラスのみ特別に多重継承が許される だから、名前も特別!
多重継承とは
複数のクラスを継承して1つのクラスを作る事
そもそもなぜクラスでは多重継承が禁止なのかというと、
複数の親クラスから継承すると、両方の親から同じ名前でありながら異なる内容のメソッドを継承してしまう可能性があるから
⇨インタフェースでは、メソッドの中身が確定しているものが1つもないので、メソッドの内容が被る可能性は全くない
よって、インタフェースでは異なる実装(メソッドの中身)が衝突する問題が発生しないため、
複数の親インタフェースによる多重継承が認められている
ex. 複数のインタフェースから多重継承する場合の宣言
public class PrincessHero implements Hero,Princess,Character{ ←この3つは全てインタフェースであること
・ インタフェースはゼロから開発(定義)せずに
既存のインタフェースを継承して(+αして)、新しいインタフェースを作ることも出来る
ex. public interface Human extends Character{
void talk( ); //+αしたい部分
// さらにこの場合、親インタフェースからrun( );が継承されている
☆ 宣言の記述方法 まとめ
継承元 継承先 ワード
クラス クラス extends
インタフェース クラス implements
インタフェース インタフェース extends
※ 中身の処理を実装する(メソッドの中身を1つでも書く)時は、implements
・ extendsとimplementsを両方使ってクラスを定義する時
implements→メソッドの中身を全て実装しなければならない(全て抽象メソッド)
extends→既に確定しているメソッドやフィールドがあるため、中身を実装しなくても良いメソッドがある
public class Fool extends Character implements Human{
//Characterクラスのメソッドは実装しないものもあるが、Humanクラスのメソッドは全て実装する
public void attack(Matango m){
中身確定
}
// Characterクラスから継承したattack( );だけabstract付きなので中身を実装する。
他の継承する前から既に中身が確定しているメソッドは、継承先で中身を確定する必要がないので、記述しない
//さらに、Humanクラスから継承した4つの抽象メソッドはImplements宣言なので、全て実装する
public void talk( ){…..}
public void watch( ){….}
public void hear( ){…}
public void run( ){…}
〈Characterクラスの中身〉
public abstract class Character{
int hp;
int mp;
public void getName( ){
return this.name;
}
public abstract void attack( ); //抽象メソッドはattackだけ
}
〈Humanインタフェースの中身〉
public interface Human{
void talk( ); //インタフェースなので、全てメソッドはabstract
void watch( );
void hear( );
void run( );
}