クラス内で静的メソッドを呼び出しますか?


166

同じクラス内の別のメソッドから静的メソッドを呼び出すにはどうすればよいですか?

$this->staticMethod();

または

$this::staticMethod();

13
あなたはこれに興味があるかもしれません(self$this):stackoverflow.com/questions/151969/php-self-vs-this
Felix Kling

参考までに、最初の例は、静的メソッドがクラスの一部であり、インスタンス変数からアクセスできないため、静的メソッドを呼び出すインスタンス変数です。
joejoeson

$ thisを削除できます。静的メソッドのみを使用し、インスタンスが存在しない場合は機能しません。
Malhal 2013年

回答:


321
self::staticMethod();

Staticキーワードの詳細。


...しかし、なぜ?$ this-> staticMethod()も機能します。なぜself :: staticMethod()の方が正しいのか(説明が正しい場合)を説明できますか?
Ian Dunn

29
@Ian Dunn簡単に言うと、$thisオブジェクトがインスタンス化$this->methodされ、既存のオブジェクト内からのみ使用できる場合にのみ存在します。オブジェクトがなく静的メソッドを呼び出すだけで、そのメソッドで同じクラスの別の静的メソッドを呼び出したい場合は、を使用する必要がありますself::。したがって、潜在的なエラー(および厳密な警告)を回避するには、を使用することをお勧めしますself
jeroen 2012年

1
ありがとう!laravelで、拡張コントローラー全体で静的メソッドを誤って呼び出していることがわかりました$thisが、コードがにプッシュされるまで問題は表面化しませんでしたstage。エラーは発生しませんでした0。値はでした。これに注意して使用してくださいself::
blamb

44

これがあなたのクラスだとしましょう:

class Test
{
    private $baz = 1;

    public function foo() { ... }

    public function bar() 
    {
        printf("baz = %d\n", $this->baz);
    }

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

foo()メソッド内から、さまざまなオプションを見てみましょう。

$this->staticMethod();

つまりstaticMethod()、インスタンスメソッドとしての呼び出しですよね?ありません。これはpublic static、インタープリターが静的メソッドとして呼び出すメソッドとして宣言されているため、期待どおりに機能するためです。そうすることで、静的メソッド呼び出しが行われていることがコードからわかりにくくなると主張できます。

$this::staticMethod();

PHP 5.3以降では$var::method()、次の意味で使用できます<class-of-$var>::。これは非常に便利ですが、上記の使用例はまだかなり慣例的ではありません。これで、静的メソッドを呼び出す最も一般的な方法がわかります。

self::staticMethod();

ここで静的呼び出し演算子である::と考える前に、別の例を挙げましょう。

self::bar();

これは、印刷されるbaz = 1ことをその手段、$this->bar()self::bar()まったく同じことを行います。それ::は単なるスコープ解決演算子だからです。静的変数へのアクセスを可能にし、機能させるためparent::self::ありstatic::ます。メソッドがどのように呼び出されるかは、そのシグネチャと、呼び出し元がどのように呼び出されたかによって異なります。

このすべての動作を確認するには、この3v4l.orgの出力を参照してください。


self::bar()誤解を招くようです-それは現在非推奨ですか?(self::静的メソッドではなくインスタンスメソッドを呼び出すために使用)。
ToolmakerSteve 2016

@ToolmakerSteveはどのようにして誤解を招くと思いますか?
ジャック・

論理的に言えば、self静的メソッドを呼び出すときはありません。定義により、静的メソッドはどこからでも呼び出すことができ、「自己」パラメータを受け取りません。それにもかかわらず、私はそのphp構文の便利さを理解しているので、あなたが書く必要はありませんMyClassName::。私は静的型付け言語に慣れています。コンパイラーには現在のスコープで使用可能なすべての変数を指定する必要があるため、(に相当する)self::を省略できます。だから一人だけ言ったself instanceMethod。言う理由はないself staticMethod
ToolmakerSteve

15

これは非常に遅い回答ですが、以前の回答にいくつかの詳細を追加します

同じクラスの別の静的メソッドからPHPの静的メソッドを呼び出す場合self、とクラス名を区別することが重要です。

たとえば、次のコードを見てください。

class static_test_class {
    public static function test() {
        echo "Original class\n";
    }

    public static function run($use_self) {
        if($use_self) {
            self::test();
        } else {
            $class = get_called_class();
            $class::test(); 
        }
    }
}

class extended_static_test_class extends static_test_class {
    public static function test() {
        echo "Extended class\n";
    }
}

extended_static_test_class::run(true);
extended_static_test_class::run(false);

このコードの出力は次のとおりです。

元のクラス

拡張クラス

これは、self呼び出し元のコードのクラスではなく、コードが含まれているクラスを参照するためです。

元のクラスを継承するクラスで定義されたメソッドを使用する場合は、次のようなものを使用する必要があります。

$class = get_called_class();
$class::function_name(); 

2
私はこの情報を見つけました。小さな意味で、私は他の答えが「誤解を招く」とは言いません。「不完全」であると言う方が正確です。self::静的メソッドAが別の静的メソッドBを呼び出し、サブクラスでBがオーバーライドされた(まれな)ケースで何が行われるのか(質問されない)質問には対応していません。私見、メソッドのオーバーライドを「インスタンス」メソッドに制限する方が混乱が少ないです。その能力は静的レベルで控えめに使用してください。別の言い方をすれば、コードの読者は、インスタンスメソッドのメソッドオーバーライド(つまり、OOコーディングの本質)を期待しますが、静的メソッドはそうではありません。
ToolmakerSteve 2016

1
非常に役立ち、クラスの拡張が元のクラスではないことは理にかなっています。したがってself、その場合には使用されないことは当然のことです。別のクラスを最初のクラスの拡張として宣言しました。self拡張クラス内で使用すると、拡張クラスを参照します。これは他の回答と矛盾しませんが、確かにの範囲を示すのに役立ちますself
iyrin 2017

2

それ以降のPHPバージョンでself::staticMethod();も機能しません。厳密な標準エラーをスローします。

この場合、同じクラスのオブジェクトを作成し、オブジェクトごとに呼び出すことができます

ここに例があります

class Foo {

    public function fun1() {
        echo 'non-static';   
    }

    public static function fun2() {
        echo (new self)->fun1();
    }
}

あなたそれを行うことができますが、fun1を使用しない場合self、それをインスタンスメソッドにすることは論理的ではありません。phpでこれを行う適切な方法は、を宣言しpublic static function fun1、次にクラスを指定して呼び出すことですFoo::fun1。それがその厳密な標準エラーを修正するための意図された方法であることは確かです。
ToolmakerSteve
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.