PHP - Является ли закрытый родительский метод переопределенным, если у ребенка есть реализация? - PullRequest
0 голосов
/ 07 июля 2019

Есть несколько вопросов о странном поведении, когда у ребенка есть реализация частного родительского метода, как в следующем примере:

class A {
    private function toOverridePrivate() {
        echo "private toOverridePrivate A\n";
    }

    public function callInA() {
        $this->toOverridePrivate();
        echo "\n";
    }
}

class B extends A {
    private function toOverridePrivate() {
        echo "private toOverridePrivate B\n";
    }  

    public function callInB() {
        $this->toOverridePrivate();
        echo "\n";
    }      
}

$a = new A;
$b = new B;

$a->callInA(); // private toOverridePrivate A

$b->callInA(); // private toOverridePrivate A
$b->callInB(); // private toOverridePrivate B

При вызове $b->callPrintsInA(), A s вызывается реализация toOverridePrivate, потому что B::toOverridePrivate не доступен из A.

Подводя итог, можно сказать, что метод должен быть доступен из области его вызова, поэтому происходит следующее:

class A {
    public function callInA() {
        $this->toOverridePrivate();
        echo "\n";
    }
}

class B extends A {
    private function toOverridePrivate() {
        echo "private toOverridePrivate B\n";
    }     
}

$b = new B;

$b->callInA(); // ERROR: Call to private method B::toOverridePrivate() from context 'A'

В последнем примере toOverridePrivate недоступен в области действия A, несмотря на то, что $this на самом деле является объектом типа B.


Но один аспект, который варьируется между ответами, заключается в том, что если есть другая реализация частного родительского метода в дочернем классе в , переопределяющем . В самом популярном вопросе я нашел "Странное поведение при переопределении приватных методов" принятый ответ говорит, что переопределение ...

Теперь, если вы переопределите закрытый метод, его новая область не будет A, это будет B

... в то время как второй по популярности ответ утверждает, что ...

Закрытый метод не может быть переопределен

... потому что это неизвестно за пределами его класса.


Последнее утверждение сомнительно, потому что объявление частного метода final делает переопределением невозможно с точным сообщением, что его нельзя переопределить:

class A { 
    final private function someMethod() { } 
}

class B extends A { 
    // Fatal error: Cannot override final method A::someMethod()
    private function someMethod() { } 
}

Итак ...

1. Дочерний класс переопределяет закрытый родительский метод, если у него есть реализация этого метода?

2. Если это не переопределение , какой словарь вы бы использовали для его описания?

1 Ответ

3 голосов
/ 08 июля 2019

Дочерний класс просто не знает никаких частных методов из родительского класса. Любой такой метод в области дочернего класса не определен. Он не может быть переопределен, если он не определен в первую очередь.

Если метод публичный, он виден всем, и любой код может его вызвать. Когда метод защищен, известно только самому классу и любому из его потомков. Когда метод является закрытым, он известен только в области действия этого класса. Для любого другого класса этот метод просто не определен.
Вы можете определить другой метод с тем же именем в дочернем классе, но он ничего не переопределяет. Вы все еще можете назвать это переопределением, но это не имеет особого смысла. Переопределение означает, что если вы не переопределите метод в дочернем классе, он вызовет определение из родительского класса. С закрытыми методами это невозможно, потому что они недоступны из дочернего класса.

Рассмотрим этот пример:

class A {
    private function toOverridePrivate() {
        echo "private toOverridePrivate A\n";
    } 
}

class B extends A {
    public function toOverridePrivate() {
        parent::toOverridePrivate();
    }   
}

$o = new B;

$o->toOverridePrivate();

Неустранимая ошибка: необученная ошибка: вызов частного метода A :: toOverridePrivate () из контекста 'B'

Независимо от того, определяет ли класс B метод toOverridePrivate или нет, не имеет значения, потому что метод toOverridePrivate из A всегда недоступен.

...