Menu
Coddy logo textTech

抽象クラス

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 25/91。

abstract class は、直接インスタンス化できない class です。他の class の設計図として機能し、子 class が実装する必要のある method を定義します。abstract キーワードを使用して abstract class を作成します。

<?php
abstract class Shape {
    protected $color;
    
    public function __construct($color) {
        $this->color = $color;
    }
    
    abstract public function calculateArea();
    
    public function getColor() {
        return $this->color;
    }
}

class Rectangle extends Shape {
    private $width;
    private $height;
    
    public function __construct($color, $width, $height) {
        parent::__construct($color);
        $this->width = $width;
        $this->height = $height;
    }
    
    public function calculateArea() {
        return $this->width * $this->height;
    }
}

$rect = new Rectangle("blue", 5, 3);
echo $rect->calculateArea();

出力:

15

Shape クラスは、実装を提供せずに抽象メソッド calculateArea() を宣言します。Shape を拡張するクラスは、このメソッドを実装する必要があります。抽象クラスには、子クラスが直接継承する getColor() のような通常のメソッドも含められることに注意してください。

抽象メソッドは子classが何をしなければならないかを定義しますが、その方法までは定義しません。これにより、すべての図形がcalculateArea()メソッドを持ちながら、それぞれの図形が異なる方法で面積を計算できます。

重要なポイント: abstract class は継承の構造と必須要件を組み合わせます。関連する class 間でコードを共有しながら、各子 class で特定の method が実装されるようにしたい場合に使用します。

challenge icon

チャレンジ

簡単

抽象クラスがどのように契約を強制しながら、異なるメディアタイプに独自の再生動作を実装させるかを示すメディアプレーヤーシステムを構築しましょう。

コードを3つのファイルに分けて整理します。

  • Media.php:すべてのメディアタイプの設計図となる抽象 Media classをDefineします。protectedな$title propertyと、titleを受け取り設定するconstructorを持たせます。子classがImplementしなければならない、play()というabstract methodを含めます。また、titleをreturnsする通常のmethod getTitle()もAddします。このconcrete methodはすべての子classに継承されます。
  • Song.phpMediaをextendsするSong classをDefineします。先頭でMedia fileをIncludeします。このclassは$artist propertyを追加します。constructorはtitleとartistを受け取るようにし、titleにはparent::__construct()を使用してから、artistを自分で設定します。必須のplay() methodをImplementし、"Playing song: [title] by [artist]"をreturnします。
  • Podcast.phpMediaをextendsするPodcast classをDefineします。先頭でMedia fileをIncludeします。このclassは$episode property(integer)を追加します。constructorはtitleとepisode numberを受け取るようにし、titleにはparent::__construct()を使用してから、episodeを設定します。必須のplay() methodをImplementし、"Playing podcast: [title] - Episode [episode]"をreturnします。

main.phpでは、Song fileとPodcast fileの両方をIncludeします。4つのinputs(song title、artist name、podcast title、episode number(stringとして受け取りintegerに変換))を受け取ります。これらのvaluesを使ってSongPodcastのobjectをCreateします。まずsongでplay()をcallingしたresultをPrintし、次にpodcastでcallingしたresultを、それぞれ別の行にPrintします。

このchallengeは、abstract classesがどのように契約をDefineするかを示します。すべてのmedia typeはplay() methodを持つ必要がありますが、それぞれのtypeは異なる方法でImplementします。abstract Media classは直接instantiatedできず、子classにstructureと共有functionalityを提供するためだけに存在します。

自分で試してみよう

<?php
require_once 'Song.php';
require_once 'Podcast.php';

// 入力を読み取る
$songTitle = trim(fgets(STDIN));
$artistName = trim(fgets(STDIN));
$podcastTitle = trim(fgets(STDIN));
$episodeNumber = intval(trim(fgets(STDIN)));

// TODO: songTitle と artistName で Song オブジェクトを作成する

// TODO: podcastTitle と episodeNumber で Podcast オブジェクトを作成する

// TODO: song で play() を呼び出した結果を出力する

// TODO: podcast で play() を呼び出した結果を出力する

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: PHPオンラインコンパイラ