2015-09-11 3 views
2

это класс структура. Я хочу, чтобы Observer: callme() также вызывался от детей.Как вызвать защищенный метод в php?

class Observer 
{ 
    protected callme() 
    { 
    } 
} 

class Parent extends Observer 
{ 
    function createChild() 
    { 
     $this->callme(); // this is OK 
     return new Child ($this); 
    } 
} 

class Child 
{ 
    private $this myParent; 
    public function __constructor ($myParent) 
    { 
     $this->myParent = $myParent; 
    } 

    public function __destroy() 
    { 
     $this->myParent->callme(); // FAIL! 
    } 
} 

так как сделать работу FAIL? (не делая его общедоступным, потому что его только для использования внутри «Родитель» и его «Дети»)

+1

Почему это защищено, если вы хотите получить к нему доступ публично? Просто сделайте это публичным, как должно быть. –

+0

, потому что его только для использования внутри «Родитель» и его «Дети» –

+1

Это не ребенок, если вы не продлеваете родителя. –

ответ

2

protected означает, что вы можете вызвать этот метод только из того же класса и из подклассов. То, что вы хотите сделать, невозможно. Ключевое слово protected было бы бессмысленным, если бы вы могли называть эти методы со всех сторон.

В C++ есть friend ключевого слова, чтобы достичь того, чего вы хотите: вы могли бы определить ребенок, как friend наблюдателя (это должно быть сделано в рамках наблюдателя), а затем вы можете вызвать все методы наблюдателя (в том числе частные и защищенный) изнутри методов Ребенка. Но для PHP такого ключевого слова не существует.

+0

да, я слышал про друга –

2

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

class Child extends Parent 
{ 
    public function __constructor() 
    { 
     parent::__constructor(); 
    } 

    public function __destroy() 
    { 
     $this->callme(); // Should work! 
    } 
} 

Или просто изменить метод для общественности.

И, btw, это код какого-то реального кода, который вы будете использовать? Этот конструктор, получающий родительский объект, кажется настолько неправильным. Что вы пытаетесь достичь?

+0

да, это нормально, но этот архитектурный проект не такой. Могут быть только один «Родитель» и многие из «Ребенка» -. «Ребенок» на самом деле не «ребенок», а скорее его содержащийся объект –

+1

Почему бы вам не поделиться своим реальным кодом или, по крайней мере, лучше понять, что вы хотите сделать, здесь есть много опытных разработчиков, которые могут помочь вам с архитектура, включая меня: D –

1

Мой комментарий к вашему вопросу объясняет, почему он не работает. Этот ответ показывает способ выполнить то, что вы просили, исходя из вашего разъяснения, что MyChild не должен распространяться MyParent.

Это пример взлома, который заставляет его работать, используя тот факт, что php не заботится о том, вызываете ли вы защищенные методы в других экземплярах, кроме вас, если вы разделяете предок защищенного метода.

Мне пришлось изменить код, чтобы сделать его действительным php. __constructor - это не имя конструктора php.

hacky.php

<?php 

class Observer 
{ 
    protected function callme() 
    { 
     echo 'I was called from ' . get_called_class(), PHP_EOL; 
    } 
} 

class MyParent extends Observer 
{ 
    public function createMyChild() 
    { 
     $this->callme(); // this is OK 
     return new MyChild ($this); 
    } 
} 

class MyChild extends Observer // hackey extends 
{ 
    private $myMyParent; 
    public function __construct($myMyParent) 
    { 
     $this->myMyParent = $myMyParent; 
     $this->myMyParent->callme(); 
    } 
} 

$p = new MyParent; 
$c = $p->createMyChild(); 

Результат:

$ php hacky.php 
I was called from MyParent 
I was called from MyParent 
0

Я думаю, я нашел решение:

class Parent extends Observer 
{ 
    function createChild() 
    { 
     $this->callme(); // this is OK 
     return new Child (function() { $this->callme(); }); 
    } 
} 

class Child 
{ 
    private $gatewayFunction; 
    public function __constructor (Closure $gatewayFunction) 
    { 
     $this->gatewayFunction = $gatewayFunction; 
    } 

    public function __destroy() 
    { 
     $this->gatewayFunction->__invoke(); 
    } 
} 

Кто собирается наделать себя? :)

+0

его не шутка, ее реальное решение. Его soooo грязный, как его приятно –