Я не так хорош как Фанат в формулировках мыслей, но попробую объяснить, как смогу.
Тут есть проблема, что реализация наследования областей видимости в пхпешном ООП отличается от канонѣчного наследования в той же Яве, частично это вызвано тем, что в пхп возможно неявное объявление переменной, частично — автокастингом типов, частично — тяжелым прошлым с обратной совместимостью.
Сначала про нормальный ООП: $this внутри методов объекта это переменная, которая ссылается на этот самый экземпляр класса (объект), в котором к ней происходит обращение. Поэтому внутри метода объекта через $this доступны все объявленные или
унаследованные свойства этого класса, независимо от их «наружной» области видимости.
Так вот private свойство отличается от protected тем, что оно
не унаследуется в классе-потомке(
но это не значит, что его нельзя переобъявить в этом потомке, поскольку в потомке его не существует)
PHP:
<?php
class A {
private $var = 1;
public function foo() {
echo $this->var;
}
}
class B extends A {
public function nice() {
echo $this->var;
}
}
$b = new B();
$b->foo(); // работает нормально, т.к. метод принадлежит к классу А, выводит 1
$b->nice(); // переменная $var не унаследовалась в класс B, ошибка
PHP:
<?php
class A {
private $var = 1;
public function foo() {
echo $this->var;
}
}
class B extends A {
private $var = 2;
public function nice() {
echo $this->var;
}
}
$b = new B();
$b->foo(); // работает нормально, т.к. метод принадлежит к классу А, выводит 1!!!
$b->nice(); // работает нормально, т.к. переменная переобъявлена в классе B, выводит 2
Теперь про статические классы (точнее их не бывает, но для простоты можно назвать этим словом статические функции со статическими переменными, объявленными в одном классе). Тут важно понять что статические классы —
это не ООП, потому что там нет объектов. Это практически, всего лишь сложные неймспейсы, такой хак, «псевдо-ООП», который тупо облегчает жизнь.
Однако у них тоже есть наследование, и в php 5.3 появилось еще позднее статическое связывание, и все это работает примерно так:
Оператор :: используется для
разрешения (вычисления) области видимости то есть говоря по-простому, он определяет в каком «неймспейсе» (статическом классе) находится функция, переменная, или константа, и вычисляет (или вызывает) ее.
Поскольку класс это не экземпляр объекта, то область видимости объявленных переменных у класса всегда равна именно этому классу.
Например, поэтому parent::$value это не вызов «родителя» объекта, а лишь «узнавание» имя
класса, который служит родителем для этого
объекта (или статического класса) и обращение к нему, как некоторой переменной (функции) в «неймспейсе».
Внутри класса self:: тоже всего лишь содержит название «неймспейса» (статического класса),
в котором он объявлен, это всего лишь «магическая» переменная, и не является аналогом ссылки на объект.
Появившийся static:: «эмулирует» наследование по правилам ООП, и добавляет возможность сослаться на тот «неймспейс», в котором
произошло обращение. Но это все равно лишь вычисляемое имя класса, в следующем примере static:: == B:: (имя статического класса, в котором произошел вызов static:: ) и это обращение к чужому методу, обьявленному как private, а значит несуществующему в области видимости класса B. Это равносильно вызову B::$var.
PHP:
<?php
class A {
private static $var = 1;
public static function foo() {
echo(static::$var); // здесь выдает ошибку "Fatal error: Cannot access property B::$var"
}
}
class B extends A {}
B::foo();
Как-то сумбурно получилось, и если где-то я не прав, то надеюсь, гуру ООП меня поправят.