PHP и классы: доступ к общему свойству родителя в родительском классе - PullRequest
2 голосов
/ 13 марта 2010

вот как выглядит мой код

У меня есть две формы:

class Form_1 extends Form_Abstract {

    public $iId = 1;

}
class Form_2 extends Form_1 {

    public $iId = 2;

}

Я ожидаю, что код ведет себя так:

$oForm = new Form_2;
echo $oForm->getId(); // it returns '2'
echo $oForm->getParentId(); // i expect it returns '1'

вот мой класс Form_Abstract:

class Form_Abstract {

    public $iId = 0;

    public function getId() {
        return $this->iId;
    }

/**
this method will be called from a child instance
*/
    public function getParentId() {
        return parent::$iId;
    }
}

но выдает фатальную ошибку:

Fatal error: Cannot access parent:: when current class scope has no parent

пожалуйста, помогите мне с методом getParentId()

PS: Я знаю причину происходящего, я ищу решение.

Ответы [ 4 ]

5 голосов
/ 13 марта 2010

Вы должны использовать Reflection Api , чтобы получить доступ к значению по умолчанию свойства родительского класса. Замените getParentId на Form_Abstract этим, и все прекрасно работает:

public function getParentId() {
    $refclass = new ReflectionClass($this);
    $refparent = $refclass->getParentClass();
    $def_props = $refparent->getDefaultProperties();

    return $def_props['iId'];
}

Очевидно, что вы не можете вызвать getParentId () в корневом классе, поэтому лучше проверить, существует ли родительский класс.

UDATE:

Вы можете сделать то же самое с функциями классов / объектов:

public function getParentId() {
    $def_values = get_class_vars(get_parent_class($this));
    return $def_values['iId'];
}
3 голосов
/ 13 марта 2010

Ошибка в том, что вы вызываете родителя класса, у которого нет родителя (он не расширяет существующий класс).

1 голос
/ 13 марта 2010

Я не думаю, что возможно даже получить доступ к "родительской" версии $iId: вы на самом деле не переопределяете ее в дочернем классе: вы только можете изменить значение, определенное в класс родителей.

Чтобы все было очень просто: когда вы объявляете класс Form_2, который extends Form_1, он берет все свойства и методы Form_2 и помещает их в Form_1, переопределяя то, что там уже существовало.
Больше нет «двух разных классов»: есть только один результирующий объект, это одновременно Form_1 и Form_2.


И вот пример, который, как я надеюсь, поможет понять, что я имею в виду:

class Form_Abstract {}
class Form_1 extends Form_Abstract {
    public $iId = 1;
    public function methodInParent() {
        var_dump($this);
    }
}
class Form_2 extends Form_1 {
    public $iId = 2;
    public function tryingToGetParentProperty() {
        var_dump(parent::$iId); 
    }
}

$form2 = new Form_2();
$form2->methodInParent();
$form2->tryingToGetParentProperty();


Используя эту часть кода, вызов $form2->methodInParent() даст вам:

object(Form_2)#1 (1) {
  ["iId"]=>
  int(2)
}

т.е.. даже если вызов / выполнение метода, определенного в родительском классе, свойство $iId остается значением, определенным в дочернем классе: существует только одна версия этого свойства!


И звонок на $form2->tryingToGetParentProperty() доставит вам:

Fatal error: Access to undeclared static property: Form_1::$iId

Так как static в Form_1.

нет свойства *1030*.


Я полагаю, что решение, позволяющее избежать этой ситуации, было бы объявить $iId как static - но учтите, что это изменит смысл вашего кода и его поведение!

т.е. переменная static будет использоваться всеми экземплярами класса, что, вероятно, не то, что вам нужно ^^

0 голосов
/ 13 марта 2010

я заставил это работать этим:

public function getParentId() {
    $sClass = get_parent_class($this);
    $tmp = new $sClass;
    return $tmp->iId;
}

НО это стандартное решение, есть ли у него проблема с производительностью ?

...