Menu
Coddy logo textTech

抽象クラス

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

抽象クラスは、直接インスタンス化できないクラスです。これは他のクラスの設計図として機能し、子クラスが実装しなければならないメソッドを定義します。abstractキーワードを使用して抽象クラスを作成します。

<?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()のような通常のメソッドも含めることができる点に注意してください。

抽象メソッドは、子クラスが何をすべきかを定義しますが、その方法は定義しません。これにより、すべての図形が calculateArea() メソッドを持つことが保証され、同時に各図形がそれぞれの面積を異なる方法で計算できるようになります。

重要なポイント: 抽象クラスは、継承の構造と強制的な要件を組み合わせたものです。関連するクラス間でコードを共有しつつ、各子クラスで特定のメソッドが確実に実装されるようにしたい場合に使用します。

challenge icon

チャレンジ

簡単

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

コードは3つのファイルに分けて構成します:

  • Media.php — すべてのメディアタイプの設計図となる抽象クラス Media を定義します。このクラスには、protectedな $title プロパティと、タイトルを受け取って設定するコンストラクタを持たせる必要があります。子クラスが必ず実装しなければならない play() という抽象メソッドを含めてください。また、タイトルを返す通常のメソッド getTitle() も追加してください。この具象メソッドはすべての子クラスに継承されます。
  • Song.phpMedia を継承する Song クラスを定義します。ファイルの先頭で Media ファイルをインクルードしてください。このクラスには $artist プロパティを追加します。コンストラクタはタイトルとアーティストを受け取るようにし、タイトルには parent::__construct() を使用し、アーティストは自身で設定します。要求された play() メソッドを実装し、"Playing song: [title] by [artist]" を返すようにします。
  • Podcast.phpMedia を継承する Podcast クラスを定義します。ファイルの先頭で Media ファイルをインクルードしてください。このクラスには $episode プロパティ(整数)を追加します。コンストラクタはタイトルとエピソード番号を受け取るようにし、タイトルには parent::__construct() を使用し、エピソードを設定します。要求された play() メソッドを実装し、"Playing podcast: [title] - Episode [episode]" を返すようにします。

main.php では、Song と Podcast の両方のファイルをインクルードします。4つの入力(曲のタイトル、アーティスト名、ポッドキャストのタイトル、エピソード番号(整数に変換する文字列として))を受け取ります。これらの値を使用して Song オブジェクトと Podcast オブジェクトを作成します。最初に曲の play() を呼び出した結果を、次にポッドキャストの play() を呼び出した結果を、それぞれ個別の行に出力してください。

このチャレンジは、抽象クラスがどのように規約を定義するかを示しています。すべてのメディアタイプは play() メソッドを持つ必要がありますが、各タイプで実装方法が異なります。抽象クラス Media は直接インスタンス化することはできません。これは、子クラスに構造と共有機能を提供するためにのみ存在します。

チートシート

抽象クラスは、直接インスタンス化できないクラスです。これは他のクラスの設計図として機能し、子クラスが実装しなければならないメソッドを定義します。抽象クラスを作成するには、abstractキーワードを使用します。

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;
    }
}

主な特徴:

  • 抽象クラスは直接インスタンス化できません
  • 抽象メソッドは、抽象クラス内では実装を持ちません
  • 子クラスはすべての抽象メソッドを実装する必要があります
  • 抽象クラスには、抽象メソッドと通常のメソッドの両方を含めることができます
  • 抽象クラス内の通常のメソッドは、子クラスに継承されます

自分で試してみよう

<?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腕試し

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

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