PHP: When would you need the self:: keyword?

2019-07-18 15:43发布

问题:

I just asked this question about the self:: keyword and didn't realize the static:: keyword existed.

It seems to me that you could use ClassName:: if you needed to reference a particular class explicitly, and otherwise you'd want self:: to mean the class that called the method. I'm trying to think of an example of when you would need self:: where you couldn't just use ClassName::.

Could you replace all occurrences of self:: with ClassName::, where ClassName is the name of the class enclosure that its found in? Not that it'd be better or even equivalent semantically, but more functionally speaking...

回答1:

self forwards static calls, while ClassName does not, in other words: it resolves to the current class instance.

There may be some cases where you want to reference to the current instance and not an extended instance of the class.

This only really matters for late static binding, seen in PHP 5.3 and up, and why the static keyword was introduced.



回答2:

I probably describe self:: as to ignore class being overwritten or polymorphic as it will always use the parent class even it has been overwritten.

class A{
  public function foo(){
    echo "hello Mike";
  }
}

class B extends A{
  public function foo(){
    echo "this will be ignore";
  }
}

$tryThis = new B();
$tryThis->foo();

// Above will print out 
// Hello Mike


回答3:

Short Answer: Yes

I was curious if this would be affected by namespace changes, inheritance or protected status on functions, but it is not. I can't think of anything else that could affect it.

I think self is better than ClassName simply because it continues to work if you change the class name on the enclosing class or paste the code into a new class.

Proof:

namespace Foo;

Class B{
    protected static function printOut()
    {
        echo "Defined in Foo\B name: ".__CLASS__."\n";
    }
}

Class A extends B{
    public static function testClassName(){
        A::printOut();
    }
    public static function testSelf(){
        self::printOut();
    }
    public static function testStatic(){
        static::printOut();
    }
}

namespace Bar;
use Foo\A as B;

Class A extends B{
    protected static function printOut(){
        echo "Defined in Bar\A name: ".__CLASS__."\n";
    }
}

$a = new A();
$b = new B();
$a->testClassname();    //Defined in Foo\B name: Foo\B
$a->testSelf();     //Defined in Foo\B name: Foo\B
$a->testStatic();       //Defined in Bar\A name: Bar\A
$b->testClassname();    //Defined in Foo\B name: Foo\B
$b->testSelf();     //Defined in Foo\B name: Foo\B
$b->testStatic();       //Defined in Foo\B name: Foo\B

As you can see, the only time Bar\A->printOut() is called is when you use static in Foo\A