PHP7から予約語がメソッド名として使えるようになっていた件

PHPで"echo"とか"list"という名前のメソッドを作って文法エラーになった経験はないでしょうか?

ほとんど知られていないのですが、実はPHP7からは"echo",“list"などの予約語がメソッド名として使えるんです。

<?php
class Foo
{
    public function list()
    {
        echo "list\n";
    }

    public function echo()
    {
        echo "echo\n";
    }

    public static function die()
    {
        echo "die\n";
    }
}


$foo = new Foo();

$foo->list();
$foo->echo();
Foo::die();

PHP 5だと文法エラーになっていた

$ php a.php
PHP Parse error:  syntax error, unexpected 'list' (T_LIST), expecting identifier (T_STRING) in a.php on line 5

PHP 7だとちゃんと動く

$ php a.php
list
echo
die

MyClass::new()とかできる

面白いことに、newという名前のクラスメソッドを作れたりします。

    public static function new()
    {
        //中身は自由に定義できる
    }

おかげでPerlと同じ言語仕様になりましたね!

なぜ使えるのか?

公式マニュアルを見ると、listやechoなどは関数名として使えないと明記されています。

http://php.net/manual/ja/reserved.keywords.php

以下のキーワードはいずれも定数、クラス名、 関数名として使用することはできません。

つまり仕様では使えないはずのものが使えている状態です。

RFCが可決されていた

実はこの新仕様はRFCが提出されており、ステータスが「PHP7.0で実装済み」となっています。

https://wiki.php.net/rfc/context_sensitive_lexer

Pull Reqeustの方を見るとマージ済みになっていてラベルが"PHP7.1"となっています。 https://github.com/php/php-src/pull/1221/

つまりPHP7.1で公式の言語仕様として採用されるものと思われます。

[追記] 公式マニュアルの隅っこにちゃんと書いてあった

実は付録のページにちゃんと書いてありました。 PHP7.0の新機能のようです。

(はてブコメントでt-cyrillさんに教えていただきました。ありがとうございました。)

予約語の制約の緩和

http://php.net/manual/ja/migration70.other-changes.php

クラスやインターフェイスそしてトレイトの内部で、 プロパティや定数そしてメソッドの名前にグローバルな予約語を使えるようになりました。 これで、今後新たなキーワードが導入された場合でも下位互換性を維持しやすくなります。 そして、API の命名の制約も軽減できるでしょう。 これは、流れるようなインターフェイスを用いた内部 DSL を作る際などに便利です。

<?php
// 'new', 'private', 'for' は、これまでなら使うことができませんでした
Project::new('Project Name')->private()->for('purpose here')->with('username here');
?>

唯一の例外は class キーワードで、このキーワードを定数名として使うことはできません。 これを許してしまうと、クラス名の解決に使う構文 (ClassName::class) と衝突してしまうからです。

個人的にこの仕様変更はとてもうれしいので大歓迎です。

PHP ++

カテゴリ: