Закрытый метод переопределения и видимости

Я с трудом пытаюсь понять вывод следующего кода:

class Bar 
{
    public function test() {
        $this->testPublic();
        $this->testPrivate();
    }

    public function testPublic() {
        echo "Bar::testPublic\n";
    }

    private function testPrivate() {
        echo "Bar::testPrivate\n";
    }
}

class Foo extends Bar 
{
    public function testPublic() {
        echo "Foo::testPublic\n";
    }

    private function testPrivate() {
        echo "Foo::testPrivate\n";
    }
}

$myFoo = new foo();
$myFoo->test();

Выход:

Foo::testPublic
Bar::testPrivate 

Класс Foo переопределяет testPublic () и testPrivate () и наследует test (). Когда я вызываю test (), существует явная инструкция, включающая в себя псевдопеременную $ this, поэтому после того, как я создал экземпляр $ myFoo, последними вызовами функции test () будут $myFoo->testPublic() и $myFoo->testPrivate() Первый вывод, как я и ожидал, поскольку я переопределил метод testPublic (), чтобы повторить Foo:: testPublic. Но второй вывод не имеет смысла для меня. Почему это Bar::testPrivate, если я переопределил метод testPrivate ()? Также приватный метод из родительского класса не будет наследоваться в любом случае, по определению! Это не имеет никакого смысла. Почему родительский метод вызывается???

1 ответ

Решение

Проблема с вашим кодом в том, что метод Bar::testPrivate является privateпоэтому он не может быть переопределен дочерними классами. Для начала я рекомендую вам ознакомиться с видимостью в PHP - http://www.php.net/manual/en/language.oop5.visibility.php. Там вы узнаете, что только public а также protected методы / свойства членов класса могут быть переопределены, private никто не может.

В качестве хорошего примера попробуйте изменить видимость Bar::testPrivate метод либо публичный, либо защищенный, без каких-либо изменений в вашем примере кода. Теперь попробуйте запустить тесты. Что просходит? Это:

Неустранимая ошибка PHP: уровень доступа к Foo::testPrivate() должен быть защищен (как в классе Bar) или слабее

Большой вопрос: "почему?". Ну, ты переопределил Bar::testPrivate с частным Foo:testPrivate, Этот новый частный метод выходит за рамки Bar::testпотому что закрытые члены класса видны только их текущему классу, а НЕ родительским / дочерним классам!

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

Другие вопросы по тегам