várias maneiras de chamar o método pai em php

90

No início, fiquei confuso por que as duas chamadas de método no construtor funcionam, mas agora acho que entendi. As classes de extensão herdam os métodos do pai como se fossem declarados na própria classe, E os métodos existem no pai, portanto, ambos devem funcionar.

Agora estou me perguntando se existe uma maneira preferencial (ou seja, prática recomendada) de chamar o método (via parentou this), e se essas são ou não maneiras realmente idênticas de executar o mesmo código, ou se há alguma advertência ao usar um o outro.

Desculpe, provavelmente estou pensando nisso.

abstract class Animal {

    function get_species() {

        echo "test";

    }

}

class Dog extends Animal {

    function __construct(){

        $this->get_species();
        parent::get_species();

    }

}

$spike = new Dog;
Jerry
fonte

Respostas:

120

Existem três cenários (que eu posso pensar) em que você chamaria um método em uma subclasse em que o método termina na classe pai:

  1. O método não é sobrescrito pela subclasse, existe apenas no pai.

    Este é o mesmo que o seu exemplo e, geralmente, é melhor usar. $this -> get_species(); Você está certo que, neste caso, os dois são efetivamente o mesmo, mas o método foi herdado pela subclasse, portanto, não há razão para diferenciar. Ao usar, $thisvocê fica consistente entre os métodos herdados e os métodos declarados localmente.

  2. O método é sobrescrito pela subclasse e tem uma lógica totalmente exclusiva do pai.

    Nesse caso, você obviamente desejaria usar $this -> get_species();porque não deseja que a versão do método parente seja executada. Novamente, ao usar consistentemente $this, você não precisa se preocupar com a distinção entre este caso e o primeiro.

  3. O método estende a classe pai, aumentando o que o método pai alcança.

    Nesse caso, você ainda deseja usar `$this -> get_species();ao chamar o método de outros métodos da subclasse. O único lugar em que você chamará o método pai seria no método que está sobrescrevendo o método pai. Exemplo:

    abstract class Animal {
    
        function get_species() {
    
            echo "I am an animal.";
    
        }
    
     }
    
     class Dog extends Animal {
    
         function __construct(){
    
             $this->get_species();
         }
    
         function get_species(){
    
             parent::get_species();
             echo "More specifically, I am a dog.";
         }
    }
    

O único cenário que posso imaginar em que você precisaria chamar o método pai diretamente fora do método de substituição seria se eles fizessem duas coisas diferentes e você soubesse que precisava da versão do método pai, não do local. Esse não deveria ser o caso, mas se ele se apresentasse, a maneira limpa de abordar isso seria criar um novo método com um nome como get_parentSpecies()onde tudo o que ele faz é chamar o método pai:

function get_parentSpecies(){

     parent::get_species();
}

Novamente, isso mantém tudo bom e consistente, permitindo mudanças / modificações no método local em vez de depender do método pai.

Anthony
fonte
como eu faria isso sem "estender"? como se eu tivesse alguma cláusula "perna" dentro da classe "humano", mas na verdade não preciso estendê-la, pois não preciso da funcionalidade "humana" do pai. agora, se eu criasse um $leg = new leg()dentro de human, como chamaria as funções humanas de dentro de uma instância de perna $leg?
user151496
@ user151496 Uma perna não é uma subclasse de humano. Um humano tem muitas pernas, mas uma perna não é um tipo de humano. Portanto, você não deve ter uma classe de perna que herda de humano, porque uma perna não é humana.
Beetle
Você faria de Leg uma classe com uma interface de Leggy? Ou apenas a classe Humana implementa Leggy? Como podemos definir melhor que uma perna não é exclusiva dos humanos, mas também que as pernas humanas são exclusivamente humanas e uma propriedade geral dos humanos?
Anthony
2
paamayim nekudotayim é um pouco confuso. À primeira vista, parece que você está chamando um método estático. Deveria ter sido parent-> get_species () ao invés
peterchaula
Acordado. As chamadas estáticas são muito confusas em muitos aspectos. Devo atualizar isso em algum momento.
Anthony
5

A menos que eu não esteja entendendo bem a questão, quase sempre usaria $ this-> get_species porque a subclasse (neste caso, dog) poderia sobrescrever esse método, uma vez que o estende. Se a classe dog não redefinir o método, ambas as formas são funcionalmente equivalentes, mas se em algum ponto no futuro você decidir que deseja que o método get_species em dog deva imprimir "dog", você terá que voltar por todo o código e mude.

Quando você usa $ this, ele é na verdade parte do objeto que você criou e, portanto, também será o mais atualizado (se a propriedade em uso mudou de alguma forma durante a vida do objeto), ao passo que usar a classe pai está chamando o método da classe estática.

hackartista
fonte
esse é um bom ponto sobre o uso de $ this caso eu queira substituir o método. Obrigado
jerry