wiele sposobów wywoływania metody macierzystej w php

90

Na początku byłem zdezorientowany, dlaczego oba wywołania metod działają w konstruktorze, ale teraz myślę, że rozumiem. Klasy rozszerzające dziedziczą metody rodzica tak, jakby były zadeklarowane w samej klasie, ORAZ metody istnieją w rodzicu, więc obie powinny działać.

Teraz zastanawiam się, czy istnieje preferowany sposób (tj. Najlepsza praktyka) wywoływania metody (przez parentlub this) i czy są to naprawdę identyczne sposoby wykonywania tego samego kodu, czy też są jakieś zastrzeżenia podczas używania jednej z nich inny.

Przepraszam, prawdopodobnie przemyślę to.

abstract class Animal {

    function get_species() {

        echo "test";

    }

}

class Dog extends Animal {

    function __construct(){

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

    }

}

$spike = new Dog;
nocnik
źródło

Odpowiedzi:

120

Istnieją trzy scenariusze (które przychodzą mi do głowy), w których można wywołać metodę w podklasie, w której metoda kończy się w klasie nadrzędnej:

  1. Metoda nie jest nadpisywana przez podklasę, istnieje tylko w rodzicu.

    To jest to samo, co twój przykład i ogólnie lepiej jest użyć opcji $this -> get_species(); Masz rację, że w tym przypadku obie są faktycznie takie same, ale metoda została odziedziczona przez podklasę, więc nie ma powodu, aby różnicować. Używając $this, zachowujesz spójność między metodami dziedziczonymi i zadeklarowanymi lokalnie.

  2. Metoda jest nadpisywana przez podklasę i ma całkowicie unikalną logikę od rodzica.

    W tym przypadku oczywiście chciałbyś użyć, $this -> get_species();ponieważ nie chcesz, aby wersja metody nadrzędna była wykonywana. Ponownie, konsekwentnie używając $this, nie musisz się martwić różnicą między tym przypadkiem a pierwszym.

  3. Metoda rozszerza klasę nadrzędną, dodając do tego, co osiąga metoda nadrzędna.

    W takim przypadku nadal chcesz używać `$this -> get_species();podczas wywoływania metody z innych metod podklasy. Jedynym miejscem, w którym nazwiesz metodę nadrzędną, będzie metoda, która zastępuje metodę nadrzędną. Przykład:

    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.";
         }
    }
    

Jedyny scenariusz, jaki mogę sobie wyobrazić, w którym musiałbyś wywołać metodę nadrzędną bezpośrednio poza metodą nadpisującą, byłby taki, gdyby robili dwie różne rzeczy i wiedziałeś, że potrzebujesz wersji metody nadrzędnej, a nie lokalnej. Nie powinno tak być, ale gdyby tak się stało, czystym sposobem podejścia do tego byłoby utworzenie nowej metody o nazwie takiej jak w get_parentSpecies()przypadku, gdy wszystko, co robi, to wywołanie metody nadrzędnej:

function get_parentSpecies(){

     parent::get_species();
}

Ponownie, dzięki temu wszystko jest ładne i spójne, pozwalając na zmiany / modyfikacje metody lokalnej zamiast polegania na metodzie nadrzędnej.

Anthony
źródło
jak bym to zrobił bez „przedłużania”? tak jak mam jakąś „nogę” w klasie „human”, ale tak naprawdę nie muszę jej rozszerzać, ponieważ nie potrzebuję funkcji rodzica „human”. Teraz, gdybym utworzył $leg = new leg()wnętrze human, jak nazwałbym funkcje ludzkie z wnętrza instancji nogi $leg?
user151496
@ user151496 Noga nie jest podklasą człowieka. Człowiek ma wiele nóg, ale noga nie jest typem człowieka. Dlatego nie powinieneś mieć takiej klasy nogi, która dziedziczy po człowieku, ponieważ noga nie jest człowiekiem.
Beetle,
Czy stworzyłbyś Leggę klasą, która ma interfejs Leggy? A może po prostu zastosuj Leggy klasy człowieka? Jak najlepiej zdefiniować, że noga nie jest wyłączną cechą człowieka, ale także, że ludzkie nogi są wyłącznie ludzkie i stanowią ogólną własność ludzi?
Anthony,
2
paamayim nekudotayim jest nieco zagmatwany. Na pierwszy rzut oka wydaje się, że wywołujesz metodę statyczną. Zamiast tego powinno to być parent-> get_species ()
peterchaula
Zgoda. Połączenia statyczne są pod wieloma względami bardzo zagmatwane. Powinienem to zaktualizować w pewnym momencie.
Anthony
5

O ile nie rozumiem źle pytania, prawie zawsze używałbym $ this-> get_species, ponieważ podklasa (w tym przypadku pies) mogłaby nadpisać tę metodę, ponieważ ją rozszerza. Jeśli klasa pies nie przedefiniuje metody, to oba sposoby są funkcjonalnie równoważne, ale jeśli w pewnym momencie w przyszłości zdecydujesz, że chcesz, aby metoda get_species w psie miała wypisać "pies", będziesz musiał wrócić przez cały kod Zmień to.

Kiedy używasz $ this, jest to faktycznie część obiektu, który utworzyłeś, więc zawsze będzie również najbardziej aktualna (jeśli używana właściwość zmieniła się w jakiś sposób w czasie życia obiektu) podczas używania klasy nadrzędnej wywołuje statyczną metodę klasy.

hackartist
źródło
to dobra uwaga przy używaniu $ this na wypadek, gdyby chciałem zastąpić metodę. Dzięki
jerry