ポンコツエンジニアのごじゃっぺ開発日記。

いろいろポンコツだけど、気にするな。エンジニアの日々の開発などの記録を残していきます。 自動で収入を得られるサービスやシステムを作ることが目標!!

【PHP】親クラスのabstract static methodを子クラスから呼び出す方法

f:id:ponkotsu0605:20200719223430p:plain

PHPでstaticメソッドを呼ぶ方法として、以下のようにselfを使って呼ぶかなと思います。(もちろんstaticの場合もあると思います)

self::foo()

抽象クラスで定義されたabstract static methodを呼び出す例

ただ、抽象クラスを定義してそこにabstract staticメソッドを作成した場合に、そのメソッドを呼び方として、以下のように書いてしまいました。

<?php

abstract class User {

    protected $name;

    function __construct($name) {
        $this->name = $name;
    }

    abstract protected static function getJobTitle(): string;

    public function getName() {
        return sprintf('%s %s', self::getJobTitle(), $this->name);    // ★selfで呼び出す
    }
}

class AdminUser extends User {
    protected static function getJobTitle(): string
    {
        return '管理者';
    }
}

$user = new AdminUser('半沢直樹');
echo $user->getName();

サンプルプログラムなので、テキトーに作成したものです。 abstractで宣言した抽象クラスであるUserクラスに getJobTitle() メソッドを定義します。 この getJobTitle() メソッドを通常のpublicメソッドである getName() からselfを用いて呼び出すプログラムです。

実行エラー

これを実行すると・・・

# php app.php

Fatal error: Uncaught Error: Cannot call abstract method User::getJobTitle() in /var/www/abstract-static-method/app.php on line 14

Error: Cannot call abstract method User::getJobTitle() in /var/www/abstract-static-method/app.php on line 14

Call Stack:
    0.0021     394216   1. {main}() /var/www/abstract-static-method/app.php:0
    0.0023     394272   2. AdminUser->getName() /var/www/abstract-static-method/app.php:26

このように、 Fatal error: Uncaught Error: Cannot call abstract method というエラーが出てしまいます。

staticを用いる

そこで、以下のようにstaticを用いて呼び出してみます。

<?php

abstract class User {

    protected $name;

    function __construct($name) {
        $this->name = $name;
    }

    abstract protected static function getJobTitle(): string;

    public function getName() {
        return sprintf('%s %s', static::getJobTitle(), $this->name);    // ★staticで呼び出す
    }
}

class AdminUser extends User {
    protected static function getJobTitle(): string
    {
        return '管理者';
    }
}

$user = new AdminUser('半沢直樹');
echo $user->getName();

実行結果

このように修正して実行すると・・・

# php app.php
管理者 半沢直樹

と、無事、呼び出すことができました。

staticとself の違い

では、staticとselfの違いとはなんでしょう? php static selfとかでググってもらえるとたくさん出ると思うのですが、自分はこの書き方が覚えやすいかもと思いました。

  • static は実行時 のクラスを指す
  • self は定義時 のクラスを指す

参考:PHP の static と self の違い | gotohayato.com

サンプルプログラムで動作確認

以下のようなサンプルプログラムを書いてみました。

<?php

class A {
    protected static function hoge() {
        return 'parent';
    }

    public function echoByStatic() {
        echo static::hoge() . PHP_EOL;
    }
    public function echoBySelf() {
        echo self::hoge() . PHP_EOL;
    }
}

class B extends A {
    protected static function hoge() {
        return 'chile';
    }
}

$b = new B();

echo 'static: ';
$b->echoByStatic();

echo 'self: ';
$b->echoBySelf();

これの実行結果は以下になります。

# php static-self.php
static: chile
self: parent

実行結果からもわかりますが、たしかにstaticは実行時のクラスを指し、selfは定義時のクラスを指すことがわかります。

さいごに

ということで、ここからもselfで呼び出すということは、抽象クラスの抽象メソッドを呼び出すということになるので、そりゃエラーになりますね、という結論に自分はなりました。

お問い合わせプライバシーポリシー制作物