PHPのself :: $ barとstatic :: $ barの違いは何ですか?


124

以下の例のselfとの違いは何staticですか?

class Foo
{
    protected static $bar = 1234;

    public static function instance()
    {
        echo self::$bar;
        echo "\n";
        echo static::$bar;
    }

}

Foo::instance();

作り出す

1234
1234

2
@deceze:同じような質問ですが、重複ではありません。これは、プロパティでのキーワードの使用について質問し、コンストラクタでのキーワードの使用について質問します。
BoltClock

回答:


190

を使用selfしてクラスメンバーを参照する場合は、キーワードを使用するクラスを参照しています。この場合、Fooクラスはと呼ばれる保護された静的プロパティを定義します$bar。あなたは、使用するときselfFooプロパティを参照するクラスは、同じクラスを参照しています。

したがってself::$barFooクラスの別の場所で使用しようとしたがBar、プロパティの値が異なるクラスがある場合は、Foo::$barではなくを使用しますがBar::$bar、これは意図したものではない可能性があります。

class Foo
{
    protected static $bar = 1234;
}

class Bar extends Foo
{
    protected static $bar = 4321;
}

あなたはときに呼び出しを経由する方法をstatic、あなたはと呼ばれる機能を呼び出すしている遅延静的バインディングを(PHP 5.3で導入を)。

上記のシナリオでは、使用selfするとFoo::$bar(1234)になります。を使用staticすると、結果はBar::$bar(4321)になります。これはstatic、インタープリターが内の再宣言を考慮に入れるためです。Barになります。実行時にクラスです。

通常、サブクラスでプロパティを再宣言しないため、プロパティではなく、メソッドまたはクラス自体にレイトスタティックバインディングを使用します。static遅延バインディングコンストラクターを呼び出すためのキーワードの使用例は、この関連質問にあります。新しい自己vs.新しい静的

ただし、これはstaticプロパティでの使用も排除していません。


子クラスで再宣言するのは非常に簡単です。親クラスは、再宣言しない限り、子クラスが使用するデフォルト値になる場合があります。親クラスにいる場合は、self ::を使用しても安全だと思います。子クラスの場合は、どちらかを使用する引数を考え出すことができますが、self ::は期待しない場合にも機能しますこれまでに再宣言します。
Andrew

3
行くphpfiddle.org、これを実行します<?php class Foo { public static $bar = 1234; public static function a( ) { echo 'static'.static::$bar; echo 'self'.self::$bar; } } class Bar extends Foo { public static $bar = 4321; } (new Bar())->a(); ?>
たYevgeniy Afanasyev

2
最初の2つの段落の文言は混乱しており、あいまいな代名詞「it」があり、後の段落で同じ情報をより明確に説明しているため、冗長でもあります。最初の2つの段落を、「上記のシナリオで」で始まる後半の段落に置き換えることをお勧めします。そのようにして、一番下の行である、簡単な答えが一番上になります。明確でわかりやすい。
ahnbizcad

これについて考える別の方法:self::$abc、内部class Fooで使用する場合はと同じFoo::$abcです。$abcサブクラスでのの再宣言の影響を受けません。AFAIKを使用する唯一の理由selfは、クラス名を使用しないようにするための省略形Fooです。[これらのすべての場所を変更せずにクラス名を変更できることも意味しますが、それがIMHOの理由の多くではありません。](PHPの名前の選択は残念であり、逆のように見えます。自然言語の単語「静的」の口語的な意味とは逆です。)
ToolmakerSteve

4

前述のように、主な違いの1つは、static遅延静的バインディングを可能にすることです。私が見つけた最も有用なシナリオの1つは、シングルトンクラスの基本クラスを作成するためのものです。

class A { // Base Class
    protected static $name = '';
    protected static function getName() {
        return static::$name;
    }
}
class B extends A {
    protected static $name = 'MyCustomNameB';
}
class C extends A {
    protected static $name = 'MyCustomNameC';
}

echo B::getName(); // MyCustomNameB
echo C::getName(); // MyCustomNameC

return static::$nameBaseクラスで使用すると、拡張時に静的にアタッチされたものが返されます。あなたが使用した場合return self::$name、その後B::getName()それは基本クラスで宣言されたものであるとして、空の文字列を返します。


0

selfコール:

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return self::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "123"
echo (new Bar)->getVar();

上記のように、クラスでをオーバーライドしました$varが、PHPに変数を明示的に要求したため、Bar123selfFoo代わり s変数を。

ここで、呼び出しをと交換するとstatic、代わりにBar上書きされた値がされます。

staticコール:

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return static::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "234"
echo (new Bar)->getVar();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.