PHP: понимание $ this - вызов метода базового класса вместо дочернего метода - PullRequest
1 голос
/ 20 марта 2020

Читая документацию PHP. net, я наткнулся на проблему, которая исказила мое понимание $ this:

class C {
    public function speak_child() {
        //echo get_class($this);//D
        echo $this->f();//calls method of C class... why?!
    }

    private function f() {
        echo "C";
    }
}

class D extends C {
    public function speak_parent() {
        echo $this->f();
    }
    public function f() {
        echo "D";
    }
}

$d= new D();
$d->speak_parent();
$d->speak_child();

Поскольку $ это представление экземпляра класса D, я бы ожидайте вывод:

DD

Но фактический вывод:

DC

Почему $ this-> f () скорее будет обращаться к методу базового класса, чем к методу дочернего класса? Ситуация меняется, когда мы изменяем C -> f на public c.

Ответы [ 2 ]

0 голосов
/ 20 марта 2020

Почему $ this-> f () скорее будет обращаться к методу базового класса, чем к методу дочернего класса?

Это дизайн. И это имеет смысл, когда вы думаете об этом. С точки зрения непрофессионала, наследование - это все о свойствах и методах, которые распространены . Поэтому самое логичное - начать с верха цепочки - уровня с наиболее распространенными методами / свойствами (чаще всего как превосходный, а не как количественный показатель). Вот упрощенная логика c:

  • Есть ли у родительского класса метод?
  • Если нет, проверьте дочерний класс. Если да, проверьте видимость.
  • Если child может переопределить метод, проверьте, есть ли у него переопределенный метод.
  • Если нет, запустите parent. Если да, запустите child.
  • Если child не может переопределить, запустите parent.

Последняя точка является ключевой для вашего примера. Родительский класс не ожидает, что у дочернего класса будет реализация того же метода. Когда вы объявляете метод в родительском классе как закрытый, вы говорите, что дочерний класс не имеет никакого отношения к этому. Поэтому нет смысла создавать метод с тем же именем внутри дочернего класса. Если у ребенка есть необходимость его использовать, то этот метод должен быть либо опубликован c, либо защищен, в зависимости от варианта использования.

$this всегда представляет экземпляр класса, который вы создали. Но вы должны помнить, что дочерний класс представляет как экземпляр самого себя, так и экземпляр родительского класса. Использование методов и свойств будет зависеть от логики c, описанной выше.

0 голосов
/ 20 марта 2020

Поскольку функция f класса C является закрытой, она не может быть перезаписана дочерним классом, дочерний класс ее не увидит. Поэтому, когда вы объявляете функцию f в дочернем классе, это новая функция, не расширенная от родительского класса.

Вы также можете расширить функцию f, если объявите ее как protected в родительском классе.

Аркодирование в официальный документ здесь

Члены, объявленные как частные, могут быть доступны только классу, который определяет член.

...