Code Fix

中級

インターフェースのメソッドを実装し忘れると Fatal error になる

implementsで宣言したインターフェースのメソッドを1つでも実装し忘れると、そのクラス自体を読み込んだ時点で致命的エラーになります。インスタンス化する前、クラスの定義そのものが不完全と判定されます。

エラーメッセージの読み方

Fatal error: Class Person contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Greeter::greet) in main.php on line 5
main.php
ファイル名
5
行番号
Fatal error
エラー種別 — 例外ではなく、クラス定義を読み込んだ時点で検出されました
Class Person contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Greeter::greet)
内容 — 何が問題だったか

このエラーが出る典型パターン

パターン1

 1  <?php
 2  interface Greeter {
 3      public function greet(): string;
 4  }
 5  class Person implements Greeter {
 6                                                       
                                ^
 7  }
 8  $p = new Person();
Fatal error: Class Person contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Greeter::greet) in main.php on line 5

PersonはGreeterインターフェースが要求するgreet()を実装していません。クラス定義が読み込まれた時点で不完全と判定され、致命的エラーになります。

直し方: (空) を public function greet(): string { return "Hi"; } にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  <?php
 2  interface Comparable {
 3      public function compareTo($other): int;
 4  }
 5  class Money implements Comparable {
 6                                                           
                                  ^
 7  }
 8  $m = new Money();
Fatal error: Class Money contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Comparable::compareTo) in main.php on line 5

MoneyはComparableのcompareTo()を実装していません。メソッド名やvisibility(public)まで一致させて実装する必要があります。

直し方: (空) を public function compareTo($other): int { return 0; } にします。

この問題を解いてみる →

パターン3

 1  <?php
 2  interface Serializer {
 3      public function serialize(): string;
 4  }
 5  class Report implements Serializer {
 6                                                           
                                  ^
 7  }
 8  $r = new Report();
Fatal error: Class Report contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Serializer::serialize) in main.php on line 5

ReportはSerializerが要求するserialize()を実装していません。クラス定義の読み込み時点でチェックされ、実装が無ければ即座にエラーになります。

直し方: (空) を public function serialize(): string { return "{}"; } にします。

この問題を解いてみる →

パターン4

 1  <?php
 2  interface Flyer {
 3      public function fly(): string;
 4  }
 5  class Bird implements Flyer {
 6                                                       
                                ^
 7  }
 8  $b = new Bird();
Fatal error: Class Bird contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Flyer::fly) in main.php on line 5

BirdはFlyerインターフェースが要求するfly()を実装していません。

直し方: (空) を public function fly(): string { return "Flap"; } にします。

この問題を解いてみる →

パターン5

 1  <?php
 2  interface Printable {
 3      public function toText(): string;
 4  }
 5  class Invoice implements Printable {
 6                                                         
                                 ^
 7  }
 8  $inv = new Invoice();
Fatal error: Class Invoice contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Printable::toText) in main.php on line 5

InvoiceはPrintableのtoText()を実装していません。

直し方: (空) を public function toText(): string { return "..."; } にします。

この問題を解いてみる →

よくある誤解

「実装していないメソッドは、呼び出したときだけエラーになるはず」という思い込みは誤りです。クラスの定義が読み込まれた時点で全メソッドの実装がチェックされ、1つでも欠けていればその場でエラーになります。

実務での勘所

PHPは全体としては動的型付け言語ですが、インターフェースの実装チェックに関しては、静的型付け言語に近い厳格さを持っています。クラスの定義がPHPエンジンに読み込まれる際、implementsで宣言したインターフェースの全メンバーが実装されているかどうかを機械的に照合し、1つでも欠けていればそのクラス定義自体を無効として扱います。動的型付け言語でありながら「契約(インターフェース)は必ず守られる」という保証だけは、実行前の検証によって型付き言語同様に確保されています。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)