Differences in the use of $ this, self, static, and parent

5

I have a question about the "appropriate" use of $ this , self , static and parent in some specific scenarios. I know the meaning and theoretical use of each:

  • $ this : basically references the instance of the object. Serves for non-static properties and methods. Can not be used with constants

  • static : same as $ this, but is used for methods, static and constant properties
  • self : used for methods, static and constant properties. In practice in a class hierarchy it references the class in
    who's self is being written

  • parent : will reference the parent class. It can be used with methods, static and constant properties

In the code below the idea of using parent was to give the visibility that the called method is an "external", or rather, inherited method. Would that be correct?

<?php

class Pessoa{     

    private $nome;
    private $idade;
    private $sexo;  

    protected function setNome($nome)
    {
        if(is_string($nome)) {
            $this->nome = $nome;
            return true;
        }

        return false;
    }

    protected function setIdade($idade)
    {
        if(is_int($idade)) {
            $this->idade = $idade;
            return true;
        }

        return false;
    }

    protected function setSexo($sexo)
    {
        if($sexo == 'M' || $sexo = "F") {
            $this->sexo = $sexo;
            return true;
        }

        return false;
    }

    public function getNome()
    {
        return $this->nome;
    }

    public function getIdade()
    {
        return $this->idade;
    }

    public function getSexo()
    {
        return $this->sexo;
    }
} 

class Funcionario extends Pessoa
{ 
    private $empresa;
    private $salario;

    public function __construct($nome, $idade, $sexo, $empresa, $salario)
    {
        parent::setNome($nome);
        parent::setIdade($idade);
        parent::setSexo($sexo);
        $this->empresa = $empresa;
        $this->salario = $salario;
    }

    public function getEmpresa()
    {
        return $this->empresa;
    }

    public function getSalario()
    {
        return $this->salario;
    }
}

$funcionario = new Funcionario("Yuri", "19", "Masculino", "Tam", "3000");

echo $funcionario->getNome() . ' Trabalha na: ' . $funcionario->getEmpresa() . ' e ganha ' . $funcionario->getSalario();

Now a macro question: Is there a recipe that suggests when it's best to use $ this , self , static / strong>?

    
asked by anonymous 20.10.2017 / 03:44

2 answers

3

Fabio, I believe that this example you posted should not be followed (that of using parent :: setName). There is no advantage, and if you use parent in this way is necessary, it is probably indicative of a design flaw.

If a class inherits methods, then you should be able to use them in the same way that you would use the methods of the inherited class.

Now suppose you need to override the setNome method in the child class. If you do, parent :: setName will not execute the overridden method, but rather the inherited class method, which would probably not be the expected result.

    
22.10.2017 / 17:45
12

The recipe is: use the one that should be used .

As you well described, the four do different things, so just use the correct , there is no better.

parent

Refers to the parent class that was inherited by the current class. Basically it was created so that you do not need, within the daughter class, to be explicit about which parent class the method will be called from, access attribute, constant, etc.

<?php

class A {
    function example() {
        echo "I am A::example() and provide basic functionality.<br />\n";
    }
}

class B extends A {
    function example() {
        echo "I am B::example() and provide additional functionality.<br />\n";
        parent::example();
    }
}

$b = new B;

// This will call B::example(), which will in turn call A::example().
$b->example();

// Saída:
// I am B::example() and provide additional functionality.
// I am A::example() and provide basic functionality.

Example taken from official documentation . See working at Ideone | Repl.it

In the code above, the example method is rewritten in B , however, its reference in A remains through parent . The only difference here, A::example() , is that you do not need to explicitly name the class that was inherited. If the name of the A class changed to W , it would suffice to only change the declaration of B , class B extends W , and not the integer code. The result is exactly the same.

this

Reference to your own instance . Everything that belongs to the instance will be available in $this . Static and constant methods belong to the class itself and therefore are not accessible in this object (in PHP). By adapting the previous example a bit, we can do:

<?php

class A {
    function example() {
        echo "I am A::example() and provide basic functionality.<br />\n";
    }
}

class B extends A {
    function example() {
        echo "I am B::example() and provide additional functionality.<br />\n";
    }

    function main() {
        $this->example();
        parent::example();
    }
}

$b = new B;

// This will call B::example(), which will in turn call A::example().
$b->main();

// Saída:
// I am B::example() and provide additional functionality.
// I am A::example() and provide basic functionality.

See working at Ideone | Repl.it

self

The reference in self always points to the class itself where it is used and this is the difference for static . When using self in A , the reference will be for class A and when used in B the reference will be B. This greatly influences, for example, when you want to define the return in a method:

<?php

class A {
    public function example() {
        return new self;
    }
}

class B extends A {

}

$b = new B();
$obj = $b->example();

echo get_class($obj), PHP_EOL;

// Saída:
// A

See working at Ideone | Repl.it

Note that setting the return as self will return an instance object of A, not B.

static

Similar to self static will always refer to the class of instance used . Sometimes the behavior of static is summarized as a self lazy , because it does not set the reference in time. Running the same example above, changing self to static , we have:

<?php

class A {
    public function example() {
        return new static;
    }
}

class B extends A {

}

$b = new B();
$obj = $b->example();

echo get_class($obj), PHP_EOL;

// Saída:
// B

See working at Ideone | Repl.it

Even if static is used in class A, the return will be a new instance of B, since new static was invoked from an instance of B and, as said, static always refers to class of the current instance.

Summarizing ...

  • parent should be used when referencing the parent class;
  • this must be used to reference the current instance;
  • self must be used to reference the class where it is applied;
  • static must be used to reference the instance class where it is applied.
20.10.2017 / 13:32