web-dev-qa-db-ja.com

PHPの抽象クラスから抽象関数を呼び出せないのはなぜですか?

抽象親クラスとそれを拡張する具象クラスを設定しました。親クラスが抽象関数を呼び出せないのはなぜですか?

//foo.php
<?php
    abstract class AbstractFoo{
        abstract public static function foo();
        public static function getFoo(){
            return self::foo();//line 5
        }
    }

    class ConcreteFoo extends AbstractFoo{
        public static function foo(){
            return "bar";
        }
    }

    echo ConcreteFoo::getFoo();
?>

エラー:

致命的エラー:5行目のfoo.phpで抽象メソッドAbstractFoo :: foo()を呼び出せません

42
Cam

これは正しい実装です。 late static bindings を使用するには、セルフではなくスタティックを使用する必要があります。

abstract class AbstractFoo{
    public static function foo() {
        throw new RuntimeException("Unimplemented");
    }
    public static function getFoo(){
        return static::foo();
    }
}

class ConcreteFoo extends AbstractFoo{
    public static function foo(){
        return "bar";
    }
}

echo ConcreteFoo::getFoo();

期待される「バー」を与えます。

これは実際にはポリモーフィズムではないことに注意してください。静的キーワークは、静的メソッドが呼び出されたクラスに解決されます。抽象静的メソッドを宣言すると、厳密な警告が表示されます。 PHPは、子(サブ)クラスに存在しない場合、親(スーパー)クラスからすべての静的メソッドをコピーするだけです。

68
Artefacto

Word self

それはAbstractClassを指しています。したがって、それは、ConcreteClass :: foo()ではなく、AbstractClass :: foo()を呼び出しています。

PHP 5.3はレイトスタティックバインディングを提供しますが、そのバージョンを使用していない場合、selfは拡張クラスではなく、関数が配置されているクラスを参照します。

参照: http://us.php.net/manual/en/function.get-called-class.php

7
Tyler Carter

abstractstaticキーワードを同時にメソッドで使用することはできません。

abstractキーワードを持つメソッドは、サブクラスがそれを実装する必要があることを意味します。クラスのメソッドにstaticを追加すると、インスタンス化せずにメソッドを使用できます。

そのため、エラーが発生します。

0
Tomheng