[オブジェクト指向]良いコード/悪いコードで学ぶ設計入門 6章 インターフェイスの概念

mino6_3プログラミング

どうも。つじけ(tsujikenzo)です。このシリーズでは、2022年5月に発売されました書籍「良いコード/悪いコードで学ぶ設計入門」についてお送りします。今日は3回目です。

前回のおさらい

前回は、「switch文の重複とクラスの肥大化」をお送りしました。

[オブジェクト指向]良いコード/悪いコードで学ぶ設計入門 6章 switch文の重複とクラスの肥大化
どうも。つじけ(tsujikenzo)です。このシリーズでは、2022年5月に発売されました書籍「良いコード/悪いコードで学ぶ設計入門」についてお送りします。今日は2回目です。前回のおさらい前回は、「この書籍と6章について...

今回は、「インターフェイスの概念」をお届けします。

今日のアジェンダ

  • 抽象化とインターフェイス
  • 型とポリモーフィズム
  • if文の排除

抽象化とインターフェイス

「四角形」や「円」などの、具体的な形を抽象化すると「図形」と言えます。

今後、具体的な形がいくら増えても、この構造に変化は起きません。 

そして、「具体的な形」を「抽象化」しているわけですから、 「図形」は安定 しています。

さらに、具体的なそれぞれの形は独立しており、安定しています。 

最終的に、抽象化した「図形」をプログラムから使うことで、プログラム全体が安定します。 

こいつのことを「インターフェイス」と呼びます。 

「インターフェイスとは、異なる型を同じ型として利用できるようにするもの」とは、 「具体的な形(四角形や円など)を、(抽象化した)図形として利用しよう」 という意味なのです。

型とポリモーフィズム

「型」とは「扱い方」です。「その値をどんな扱い方するんですか?」という問いに答えたものです。

ソースコード中の「3」という値に対して、どんな扱い方をするの?と問いかけたとき、 「文字列として扱うよ」と答えたものが「文字列型」 です。

リアルな世界の「〇」というものに対して、「円として扱うよ」と答えたのが「円型」です。

しつこいですが、「あなたが、これから扱おうとしてる〇だか□だかわかりませんが、それ、なんて言って扱うんですか?」に答えたのが「図形型」です。

抽象クラスであるインターフェイスには、処理の中身 {} を持たないメソッド(具象から抽象化したメソッドだからです)を定義します。

interface Shape{
  double area();
}

具象クラスと実装

いっぽう、四角形や円などのクラスを、「具象クラス」と呼びます。

具象クラスでは、インターフェイスの抽象メソッドの中身を実装します。これは、メソッドのオーバーライドです。

/** Rectangleクラス */
class Rectangle implements Shape {
  //省略
  // オーバーライドによる実装
  public double area() {
    return width * height;
  }
}

if文の排除

以上で2つのクラスが定義できました。

  • 抽象メソッドをもつ、抽象クラス(インターフェイス)の「図形」
  • 具象メソッドをもつ、具象クラスの「長方形」

そして、長方形と図形は具体と抽象の関係にあるので、「長方形を(あたかも)図形型として扱える」というのがポリモーフィズムです。

多態性とか多相性と、呼ばれる仕組みです。

/** 実行用エントリポイント */
class Sample6_24 {
  public static void main(String[] args) {
    Shape shape =new Rectangle(10, 10); //長方形クラスのインスタンスを図形型として扱う
    System.out.println(shape.area()); // 図形型なので、shape.area()で呼び出せる。A.100
    shape = new Circle(10); //円クラスのインスタンスを図形型として扱う
    System.out.println(shape.area()); // 図形型なので、shape.area()で呼び出せる。314.1592653589793
   }
}

ポリモーフィズムによって、すべての具体的な型たちを「図形型」として扱えるようになったので、もはや型判定をする必要がなくなります

このように、型判定のif文を無くすことができます。

//どこかに書かれているだろう処理
class ShowArea {
  static double showArea(Shape shape) {
    return shape.area(); 
    }
}

interface Shape {
  double area();
}

/** Rectangleクラス */
class Rectangle implements Shape {
  private final double width;
  private final double height;

  Rectangle(double width, double height) {
    this.width = width;
    this.height = height;
  }

 // オーバーライドによる実装
 public double area() {
  return width * height;
 }
}

/** Circleクラス */
class Circle implements Shape {
  private final double radius;
  
   Circle(double radius) {
    this.radius = radius;
   }

  // オーバーライドによる実装
  public double area() {
    return radius * radius * Math.PI;
  }
}

/** 実行用エントリポイント */
class Sample6_26 {
  public static void main(String[] args) {
  Shape shape = new Rectangle(10, 10);
  System.out.println(shape.area()); // 100

  shape = new Circle(10);
  System.out.println(shape.area()); // 314.1592653589793
  
  // ShowArea処理を使う
  shape = new Rectangle(10, 10);
  System.out.println(ShowArea.showArea(shape)); // 100.0
  }
}

JavaScriptでも書いてみましょう。

minodriven-goodcodebadcode/Section6/myFunction6_4.js at main · tsujike/minodriven-goodcodebadcode
ミノ駆動本のソースコードです。. Contribute to tsujike/minodriven-goodcodebadcode development by creating an account on GitHub.

糖衣構文って、やっぱりすごいですね。

まとめ

以上で、「インターフェイスの概念」をお送りしました。

インターフェイス(風な記述)をJavaScriptで書くと、どこがよくないのかという考察は、別途行いたいと思います。

次回は、「インターフェイスとアプリケーション設計」 をお届けします。

参考資料

このシリーズの目次

タイトルとURLをコピーしました