Доступ к статическим переменным дочернего класса из родительского класса?

У меня есть базовый класс, который мне нужно вызвать функции класса, на который ссылается дочерний класс.

Достаточно легко,

class base_class {

    public function doSomethingWithReference(){
        $this->reference->doSomething();
    }
}

class extended_class extends base_class{

    protected $reference;

    public function __construct($ref){
        $this->reference = $ref;
    }
}

Теперь это отлично работает,

Но, когда я отлаживаю, мне не важно значение $this->reference

Но объект, на который ссылается $this->reference, огромен!

поэтому, когда я делаю print_r($instanceOfExtendedClass), я получаю распечатку этого объекта.

Теперь ссылка для каждого класса отличается от base_class.

Я хотел просто установить reference как статическое свойство в классе extended_class.

Но, изменив doSomethingWithReference на self::$reference, выдается ошибка переменной undefined.

И наоборот установка статической переменной в base_class и ее изменение из extended_class не работает, поскольку она изменяет переменную для всего, что распространяется от этого класса.

Есть ли способ сделать это, поэтому я не получаю распечатку из $this->reference?

Ответ 1

Поскольку вы используете PHP 5.3, вы можете использовать позднюю статическую привязку для разрешения статического вызова в класс справа во время выполнения.

class base_class {

    public function doSomethingWithReference(){
        static::$reference->doSomething();
    }

}

class extended_class extends base_class{

    protected static $reference;

    public function __construct($ref){
        static::$reference = $ref;
    }

}

Напоминание большого жира. Этот extended_class::$reference будет разделяться среди всех экземпляров extended_class. Если это не то, что вы намереваетесь, это не сработает.

Кажется, вы действительно беспокоитесь об использовании памяти или ресурсов. В PHP все объекты передаются по ссылке. Это означает, что передача объекта в качестве аргумента или создание его копии и т.д. Не требует дополнительной памяти. Если вам нужно ссылаться на объект в целом ряде других объектов, это не потребует дополнительной памяти.


Если бы у меня был extended_class и другой идентичный класс (скажем, extended_class1), они бы разделили ссылку? или все экземпляры extended_class будут иметь одну ссылку, а все экземпляры extended_class1 будут делиться другим (идеальным случаем)?

Похоже, что общий доступ основан на определении статической переменной. Два примера, как из интерактивного приглашения PHP:

php > class Shared { public $me; public function __construct($me) { $this->me = $me; } }
php > class Base { protected static $ref; public function foo() { echo static::$ref->me, "\n"; } }
php > class Inherit_1 extends Base { public function __construct($ref) { static::$ref = $ref; } }
php > class Inherit_2 extends Base { public function __construct($ref) { static::$ref = $ref; } }
php > class Inherit_3 extends Inherit_1 {}
php > $shared_1 = new Shared(1)
php > ;
php > $shared_2 = new Shared(2);
php > $shared_3 = new Shared(3);
php >
php > $in_1 = new Inherit_1($shared_1);
php > $in_2 = new Inherit_2($shared_2);
php > $in_3 = new Inherit_3($shared_3);
php >
php > $in_1->foo();
3
php > $in_2->foo();
3
php > $in_3->foo();
3

В этом случае, поскольку эта ссылка находится в базовом классе, каждый видит один и тот же. Полагаю, это имеет какой-то смысл.

Что происходит, когда мы объявляем ссылку с каждым дочерним классом. большую часть времени?

php > class Shared { public $me; public function __construct($me) { $this->me = $me; } }
php > class Base { public function foo() { echo static::$ref->me, "\n"; } }
php > class Inherit_1 extends Base { protected static $ref; public function __construct($ref) { static::$ref = $ref; } }
php > class Inherit_2 extends Base { protected static $ref; public function __construct($ref) { static::$ref = $ref; } }
php > class Inherit_3 extends Inherit_1 {}
php > class Inherit_4 extends Inherit_1 { protected static $ref; }
php > $shared_1 = new Shared(1);
php > $shared_2 = new Shared(2);
php > $shared_3 = new Shared(3);
php > $shared_4 = new Shared(4);
php > $in_1 = new Inherit_1($shared_1);
php > $in_2 = new Inherit_2($shared_2);
php > $in_3 = new Inherit_3($shared_3);
php > $in_4 = new Inherit_4($shared_4);
php > $in_1->foo();
3
php > $in_2->foo();
2
php > $in_3->foo();
3
php > $in_4->foo();
4

Поскольку 3 унаследовал от 1 без объявления его собственного статического свойства, он унаследовал 1. Когда мы установили 3 в Shared (3), он перезаписал 1 существующий Shared (1).

Заключение. Чтобы это сработало, свойство должно быть объявлено в каждом классе, для которого требуется единственная уникальная ссылка. Обратите внимание, что этот код действителен с 5.4.x.

Ответ 2

Предоставить родительскому пути доступ к статическому члену дочернего элемента:

<?php

abstract class base_class {
    abstract protected function reference();
    // If you want to be able to instanciate base class directly, use the following 2 lines in place of the previous 2 lines:
//class base_class {
    //protected function reference() {}

    public function doSomethingWithReference(){
        $this->reference()->doSomething();
    }
}

class extended_class extends base_class{
    protected static $reference;

    public function __construct($ref){
        self::$reference = $ref;
    }

    protected function reference(){
        return self::$reference;
    }
}

class ref {
    public function doSomething(){
        echo __METHOD__;
    }
}

$ref = new ref();
$ec = new extended_class($ref);
$ec->doSomethingWithReference();

print_r($ec);
?>