2014-02-09 2 views
2

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

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(), и наследует тест(). Когда я называю тест(), имеется явная инструкция envolving $ это псевдо переменной, поэтому после того, как я создал $ MYFOO экземпляра, окончательные вызовы теста() функция будет $ myFoo-> testPublic() и $ myFoo-> testPrivate(). Первый вывод, как я и ожидал, так как я перепробовал testPublic() метод для эха Foo :: testPublic. Но второй вывод не имеет для меня никакого смысла. Почему это Бар :: testPrivate if I overrode testPrivate() метод? Также частный метод из родительского класса не будет наследоваться, по определению! Это не имеет никакого смысла. Почему родительский метод называется вызываемым ???

+0

Рассмотрите возможность изменения 'public function test() { $ this-> testPublic(); $ this-> testPrivate(); } 'to' public function test() { $ this-> testPublic(); static :: testPrivate(); } '- затем прочитайте о [позднем статическом привязке] (http://www.php.net/lsb) (в частности, примере № 3) –

+0

@MarkBaker эти методы вызывают в контексте объекта, а не статичны, поэтому поздняя статическая привязка делает не применять. Это была простая проблема видимости. – Mark

+1

@rainfromheaven - я специально ссылался на __Example # 3__ в своем комментарии: «static :: use в контексте __non-static__» .... т. Е. В вопросе __объекта__.Последнее статическое связывание применяется точно так же, как указано в этой части документов. –

ответ

4

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

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

PHP Fatal error: Access level to Foo::testPrivate() must be protected (as in class Bar) or weaker

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

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

+0

Верьте или нет, код, который я разместил, из предложенной вами ссылки, PHP официальное руководство, касающееся части видимости. Это часть примера №2. – renatov

+1

Да, и хотя в этом примере отсутствует объяснение того, что он делает, это на самом деле иллюстрирует, что означает «частная» видимость с точки зрения переопределения метода (что он ** не может быть выполнен **). – Mark

+0

О, я понимаю это сейчас. Но у меня есть другой вопрос. «Защищенный» метод не должен быть доступен из других объектов, но таким образом он был доступен, правильно? Это похоже на обходной путь для вызова защищенного метода. Разве это не нарушение инкапсуляции? – renatov

Смежные вопросы