第10回 インターフェースについて

公開日:2014-10-14

1. 概要

独り言によるプログラミング講座「第10回 インターフェースについて」です。
インターフェースについて説明しています。

2. 動画


関連動画

3. 補足

インターフェースは、異なるクラスの共通の規格(ルール・仕様)のようなものです。
同じインターフェースであれば、異なるクラスであっても、同様に使うことができます。
クラスの利用者は、各クラスの使用方法をそれぞれ知る必要はなく、
インターフェースの使用方法だけ把握するだけで済みます。

クラスを new して生成されたオブジェクトは、
代入する変数の型(クラス、インターフェース)を変えても、元々のオブジェクトの型は変わりません。
変わるのはあくまでも、外から見える部分のみです。
ガチャガチャに似てます。
カプセルが変数の型(クラス、インターフェース)で、中に入っている物がオブジェクトになります。
オブジェクトは、型さえあっていれば、いつでも他の型へ入れ替えて、外見を変えることができます。

インターフェースは、変数の値を保持する型のため、new して生成することができません。

インターフェースは外側から見える定義のみで、
実際の処理を書くことが出来ないため、各クラス共通の処理は、
別のクラスに定義するなどして、コード量を減らす必要があります。
そのため、状況によっては、クラスのファイル数が増えて逆にわかりづらくなったり、
コード量が増えて、実装が大変になる場合があります。
また、バグが発生した場合に、抽象化されすぎて、
どのクラスが動いてバグが発生したのかがわかりづらい場合もあります。

以下はインターフェースを使ったサンプルです。
スポーツカーと軽自動車は、車インターフェースを実装しているため、
どちらも同じ方法で使用できますし、
どちらも駐車場に駐車することができます。
クラス
interface 車 {
  void アクセル();
}

class スポーツカー : 車 {
  public void アクセル() {
    スピード = スピード + 100;
  }
}

class 軽自動車 : 車 {
  public void アクセル() {
    スピード = スピード + 5;
  }
}

class 駐車場 {
  車 _car;
  public static void 駐車(車 car) {
    _car = car;
  }
}
使用方法
//インターフェースが同じため、各クラスを同じ操作方法で使用できる。

車 car1 = new スポーツカー();
car1.アクセル();  //スピードが 100 上がる

車 car2 = new 軽自動車();
car2.アクセル();  //スピードが 5 上がる

//引数の型を車にしているため、スポーツカーでも、軽自動車でも、どちらも駐車できる。
駐車場.駐車(car1);
駐車場.駐車(car2);

もし、インターフェースを使わずに、以下のようになっていた場合、
型が限定されてしまうため、スポーツカーしか駐車できなくなります。

ソース
class 駐車場 {
  スポーツカー _car; //駐車する車
  public static void 駐車(スポーツカー car) {
    _car = car;
  }
}

上記をインターフェースを使わずに対応しようとすると、
型ごとにメソッドを増やす必要があり、似たようなコードが増えます。
使用する側もメソッドを呼び分ける必要があり、不便です。
このため、メソッドの内部の処理だけ異なるようなクラスを複数作る場合は、
インターフェースを検討する必要があります。
ソース
class 駐車場 {
  スポーツカー _car1;
  軽自動車     _car2;
  public static void 駐車_スポーツカー用(スポーツカー car) {
    _car1 = car;
  }
  public static void 駐車_スポーツカー用(軽自動車 car) {
    _car2 = car;
  }
}

また、車種を持たせた自動車クラスを作れば、
インターフェースを使わなくても、インターフェースを使った場合と同じようなことはできます。
自動車クラス側の各メソッドで、車種ごとに分岐が必要になりますが、
今後も分岐が増える予定がない場合は、これでも問題ありません。
インターフェースを使用するかどうかは、今後の拡張性を含めて、状況に応じて選択する必要があります。
ソース
class 自動車 {
  public void string 車種;
  public void アクセル() {
    if (車種 == "スポーツカー") スピード = スピード + 100;
    if (車種 == "軽自動車")     スピード = スピード + 5;
  }
}

class 駐車場 {
  自動車 _car;
  public static void 駐車(自動車 car) {
    _car = car;
  }
}

自動車 car = new 自動車();
car.車種 = "スポーツカー";
car.アクセル();
駐車場.駐車(car);