Moment For Technology

Static, $this, self, parent, and late static binding

Posted on Dec. 3, 2022, 10:09 a.m. by Johnny Woods PhD
Category: The back-end Tag: php The back-end

This is the 9th day of my participation in the More text Challenge. For details, see more text Challenge

An in-depth analysis of pronouns and a guide to avoiding pitfalls

There are very few people on the Internet who really say these pronouns clearly. And they're so important, you fall into a pit if you don't use them well. I'm going to summarize the use and differences of these pronouns in PHP classes, and the pitfalls.

Let's start with the most complex static.

static

Static can be used in three ways:

  1. Static, which we discussed in the static article, will not be discussed here, but is used to declare properties and member methods before they can be called without instantiation, and to bind static properties to the class.

  2. A pronoun can be used in an expression for a member method to refer to the class that called it.

  3. The return value type of a member method, used in a member method declaration, restricts the return value to be an object of the calling class;

Here's an example:

class Product {               
    public static function getNew( ): static {     
        $new = new static;   
        return $new;
    } 
}
class SubProduct extends Product{
}

$p1 = Product::getNew( );
$p2 = SubProduct::getNew();
var_dump($p1);    //object(Product)#24
var_dump($p2);    //object(SubProduct)#27
Copy the code

This example uses the last two uses of static:

  1. The data return type is static, which restricts the return value to be an object of the calling class. So in this case the superclass Product calls, then the object returned must also be an object of Product;

  2. $new= new static; Static refers to the name of the class that called it. So SubProduct:: static refers to SubProduct, which translates to $new= new SubProduct, an object creation statement.

Just remember that static is used in the body of a method and refers to the class of the person who called it.

When this "it" is a class, as in the example above, it's a static call; When it is an instantiated object, it is a nonstatic call.

Simple, isn't it? So before you get too self-assured, I'll leave you with a few other pronouns, and then I'll come back to this static call.

$this

$this is a reference to the current object. Simply put, I am who calls me.

$this cannot be used to access static properties because they are bound to the class and can only be accessed by static, self, and parent.

Here's an example of what $this means:

class MyClass1
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';

    function printHello()
    {
        echo $this-public;
        echo $this-protected;
        echo $this-private;
    }
}

class MyClass2 extends MyClass1
{
    public $public = 'Public2';
    protected $protected = 'Protected2';
    private $private = 'Private2';
}

$obj = new MyClass1();
$obj - printHello();   //Public Protected Private
$obj2 = new MyClass2();
$obj2 - printHello();  //Public2 Protected2 Private
Copy the code

$this-public = $obj2-public = $obj2-public = $obj2-public = $obj2-public

$obj2-printHello(); $obj2-printHello(); $obj2-printHello(); $obj2-printHello();

When an object contains two properties of the same name, the properties of that class are returned from which the class is called.

Nearby principle

The proximity principle of $this applies to private member methods as well as private attributes. Static, self, parent don't have that feature. Let's take an example:

class AA { private function foo() { echo "success! \n"; } public function test() { $this-foo(); static::foo(); } } class BBBB extends AA { } class CCC extends AA { private function foo() { echo 'CCC'; } } $b = new BBBB(); $b-test(); //Success Success $c = new CCC(); $c-test(); //Success error:Call to private method CCC::foo() from scope AACopy the code

Let's start with the BBBB subclass, which fully inherits the methods of the AA superclass. $this-foo() = $b-foo(); static::foo() = A::foo();

CCC inherits two methods from AA; private function foo() inherits two methods from AA. But at the same time, it also has its own private function foo(), so it has two methods with the same name. At this point, $this and static refer to different results.

CCC::foo () = CCC::foo (); CCC::foo () = CCC::foo (); test() = AA;

$this-foo(); We mentioned that $this has a proximity principle for private properties and methods, meaning that the class in which it is called refers to that class.

$this-foo() $this-foo() $this-foo() If you subclass test() from the above example, the output will be 'CCC', which you can verify locally.

To summarize: $this refers to the object being called, but when dealing with private properties and methods, it follows the proximity principle and refers to the class where the method belongs

self parent

I put these two together because they have something in common: parent is the parent class of the member method.

In this example, let's take a look at what self, parent, and static mean:

Class fooo {public function something() {echo __CLASS__; Var_dump ($this); // Return the name of the class where the current method resides. }} class fooo_bar extends fooo {public function something() {echo __CLASS__; // fooo_bar var_dump($this); } public function call() {echo self::something(); // self echo parent::something(); // parent echo static::something(); // current}} class fooo_bar_baz extends fooo_bar {public function something() {echo __CLASS__; // fooo_bar_baz var_dump($this); } } $obj = new fooo_bar_baz(); $obj-call(); //**output**: fooo_bar fooo fooo_bar_bazCopy the code

Ok, in the example above, I build a parent class, a child class, and a grandchild class, and create member methods in the subclass to call the member methods of the three classes, and then create objects in the grandchild class to call the methods of the subclass.

  1. Self refers to the class of the method, regardless of who called it, so in this case it's fooo_bar;

  2. Parent refers to the parent class of the class where the current method is located. It doesn't matter who called it, so even if it's called by a grandchild, it still refers to the parent class of the subclass fooo.

  3. Static, as we mentioned in the first section, is bound to the calling class, where $obj belongs to the grandchild, so the output is fooo_bar_baz;

  4. __CLASS__ is a magic variable in PHP that, like get_class(), returns the class name of the calling object;

Static Late static binding pit

Do you feel like you have these pronouns in mind? Don't be so sure about yourself. Let's take a look at the original pit: static calls.

To explain what static calls are, they are direct access to static variables and static methods by using double quotes ::.

A non-static call is made by the instantiated object via -.

When static meets static, something amazing happens:

class A { public static function foo() { static::who(); } public static function who() { echo __CLASS__."\n"; } } class B extends A { public static function test() { A::foo(); parent::foo(); self::foo(); } public static function who() { echo __CLASS__."\n"; } } class C extends B { public static function who() { echo __CLASS__."\n"; } } C::test(); // Result: A C CCopy the code

How's that´╝č Have you been hit in the face by the results above? The first time I thought it was "AU AU BU", I got hit in the face.

This is because static is a little different when called statically:

In the case of a static call, it refers to the explicitly specified class, regardless of which pronouns pass in between. This is known as "late static binding," where static refers to the class that was called on the previous non-forwarding call.

In other words, the so-called "non-forward call" refers to the explicitly specified class. C:: and A:: in the example above do not need to forward, it is directly clear which class is calling.

So "forward call" is self::, parent::, static::, doesn't specify the class name, it just does the class name forward.

Ok, now let's look at the example above again:

  1. A, the result is straightforward, because A:FOO() is specified in test(), so static in FOO() refers to the explicitly specified A, calling A:WHO;

  2. Parent :foo(); self:foo(); parent:foo(); self:foo();

  3. In combination with static invocation, static refers to the explicitly specified class, and self and parent simply forward C::, so static refers to both C::, so it outputs two C's

** This feature is available only when the static keyword is used. ** This feature is available only when the static keyword is used

I've put together a table to make it clearer what these four pronouns refer to and how they differ:

Thank you for reading and introducing jade. If there are any inaccuracies and mistakes, please make corrections. I will reply in time.

Welcome to learn programming partners and I communicate, learn together, grow together!

Summary is not easy, please do not reprint, otherwise don't blame the old man you are welcome!

References:

www.php.net PHP official documentation

Search
About
mo4tech.com (Moment For Technology) is a global community with thousands techies from across the global hang out!Passionate technologists, be it gadget freaks, tech enthusiasts, coders, technopreneurs, or CIOs, you would find them all here.