кілька способів виклику батьківського методу в php


90

Спочатку мене бентежило, чому обидва виклики методу працюють у конструкторі, але тепер, думаю, я розумію. Розширювані класи успадковують батьківські методи так, ніби вони були оголошені в самому класі, І методи існують у батьківському, тому обидва повинні працювати.

Зараз мені цікаво, чи є кращий спосіб (тобто найкраща практика) виклику методу (через parentабо this), і чи справді це однакові способи виконання одного і того ж коду, чи є застереження при використанні одного з інші.

Вибачте, я, мабуть, над цим думаю.

abstract class Animal {

    function get_species() {

        echo "test";

    }

}

class Dog extends Animal {

    function __construct(){

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

    }

}

$spike = new Dog;

Відповіді:


120

Є три сценарії (які я можу придумати), коли ви викликали б метод у підкласі, де метод виходить із батьківського класу:

  1. Метод не перезаписується підкласом, він існує лише в батьківському.

    Це те саме, що і ваш приклад, і загалом краще скористатися. $this -> get_species(); Ви маєте рацію, що в цьому випадку ці два фактично однакові, але метод успадкований підкласом, тому немає причин диференціювати. За допомогою $thisви залишаєтеся послідовними між успадкованими методами та локально оголошеними методами.

  2. Метод замінюється підкласом і має абсолютно унікальну логіку від батьківського.

    У цьому випадку ви, очевидно, хочете використовувати, $this -> get_species();оскільки не хочете, щоб виконувалася батьківська версія методу. Знову ж таки, послідовно використовуючи $this, вам не потрібно турбуватися про різницю між цією справою та першою.

  3. Метод розширює батьківський клас, додаючи до того, чого досягає батьківський метод.

    У цьому випадку ви все одно хочете використовувати `$this -> get_species();при виклику методу з інших методів підкласу. Викликати батьківський метод можна лише в тому методі, який замінює батьківський метод. Приклад:

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

Єдиний сценарій, який я можу собі уявити, де вам потрібно буде викликати батьківський метод безпосередньо за межами перевизначуючого методу, якщо вони роблять дві різні речі, і ви знаєте, що вам потрібна батьківська версія методу, а не локальна. Це не повинно бути так, але якби він справді представився, то чистим способом підійти до цього було б створити новий метод з іменем, get_parentSpecies()де все, що він робить, це викликати батьківський метод:

function get_parentSpecies(){

     parent::get_species();
}

Знову ж таки, це робить все приємним і послідовним, дозволяючи змінювати / модифікувати локальний метод, а не покладатися на батьківський метод.


як би я це зробив без "продовження"? як у мене є якась класова "ніжка" всередині класу "людина", але мені насправді не потрібно її розширювати, оскільки мені не потрібна батьківська "людська" функціональність. тепер, якби я створив $leg = new leg()усередині human, як би я викликав людські функції зсередини екземпляра ноги $leg?
user151496

@ user151496 Ніжка не є підкласом людини. У людини багато ніг, але нога не є типом людини. Тому ви не повинні мати клас ніг, який успадковується від людини, тому що нога не є людиною.
Жук

Ви б зробили Leg класом, який має інтерфейс Leggy? Або просто у класу Human застосувати Leggy? Як ми можемо найкраще визначити, що нога не є винятковою для людини, а також те, що людські ноги - це однозначно людські та загальні властивості людей?
Ентоні

2
paamayim nekudotayim трохи заплутаний. На перший погляд здається, що ви викликаєте статичний метод. Натомість воно мало бути батьківським> get_species ()
peterchaula

Домовились. Статичні дзвінки в багатьох аспектах дуже заплутані. Я повинен оновити це в якийсь момент.
Ентоні

5

Якщо я не розумію питання, я майже завжди використовував би $ this-> get_species, оскільки підклас (у цьому випадку собака) міг би переписати цей метод, оскільки він його розширює. Якщо клас собаки не перевизначає метод, тоді обидва способи функціонально еквівалентні, але якщо в якийсь момент у майбутньому ви вирішите, що хочете, щоб метод get_species у собаці надрукував "собака", то вам доведеться повернутися назад через весь код зміни це.

Коли ви використовуєте $ this, це насправді частина об'єкта, який ви створили, і тому завжди буде також найсучаснішим (якщо використовувана властивість якось змінювалася протягом життя об'єкта), тоді як використання батьківського класу викликає метод статичного класу.


це хороший момент щодо використання $ this на випадок, якщо я хочу замінити метод. Дякую
Джеррі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.