【问题标题】:Access child class static variables from parent class?从父类访问子类静态变量?
【发布时间】:2012-12-08 04:52:53
【问题描述】:

我有一个基类,我需要在子类中引用的类上调用函数。

很简单,

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 会引发未定义变量错误。

相反,在base_class 中设置静态变量并从extended_class 修改它不起作用,因为它会更改从该类扩展的所有内容的变量。

有没有办法做到这一点,所以我不会打印出$this->reference

【问题讨论】:

  • 您使用的是哪个 PHP 版本?有一些big changes to static behavior in 5.3,如果你被困在旧的东西上会给你一个非常不同的答案。
  • 这个类结构违反了一些东西,我只是不确定它是什么:)

标签: php reference static static-members


【解决方案1】:

由于您使用的是 PHP 5.3,因此您可以使用 late static binding 在运行时解析对正确类的静态调用。

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 起有效。

【讨论】:

  • 我实际上并不担心内存,它只是为了调试,我不喜欢滚动大约 600 行(Code Igniter 对象!)来查看对象属性是什么!你关于extended_class::$reference 共享参考的观点,如果我有extended_class 和另一个相同的类(比如extended_class1),他们也会共享参考吗?还是所有 extended_class' 实例共享一个引用,而所有 extended_class1' 实例将共享另一个(理想情况)?
  • @Hailwood,我已经更新了我的答案,并通过测试演示了静态属性的解决位置。
【解决方案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);
?>

【讨论】:

  • -1,这只是一个代码转储。您还没有解释这段代码是什么,它为什么工作,它是如何工作的,以及它是如何回答问题的。
  • 感谢您的批评,@Charles - 无意讽刺。事实上,为您的评论 +1。将来,我肯定会更加详细,而不是假设读者仅仅通过阅读代码就能理解正在发生的事情。我手边没有 PHP
猜你喜欢
  • 2017-05-21
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 2012-07-25
相关资源
最近更新 更多