15

我现在正在编写的应用程序和这个人有同样的问题。问题是子类中没有继承静态属性,因此如果我在主类中使用 static:: 关键字,它也会在我的主类中设置变量。

如果我在子类中重新声明静态变量,它会起作用,但我希望有大量的静态属性和子类,并希望避免代码重复。我链接的页面上评分最高的响应有一个指向一些“解决方法”的链接,但它似乎有 404'd。谁能给我一些帮助,或者指出我所说的解决方法的方向?

4

3 回答 3

9

我不确定它在谈论什么具体的解决方法,我能想到很多可行的方法。我个人不会在任何代码中使用这些。我建议您看一下是否有可能在 PHP 中过度使用后期静态绑定?并重新考虑是否有更好的方法来做你希望完成的任何事情。

另外请记住,我的代码完全未经测试,因为我只是在这里编写的。

方法一:总是用数组来图

所有其他方法均基于此方法。无论您在何处使用静态属性,您都可以插入代码来检测类并获取它。如果您从不打算在其他任何地方使用该物业,我只会考虑这一点。

$class = get_called_class();
if(isset(self::$_names[$class])) {
    return self::$_names[$class];
}
else {
    return static::NAME_DEFAULT;
}

方法 2:使用 getter/setting 方法

如果您打算在多个地方使用它,这种方法会更好。一些单例模式使用类似的方法。

<?php
class SomeParent {
    const NAME_DEFAULT = 'Whatever defaults here';

    private static $_names = array();

    static function getName($property) {
        $class = get_called_class();
        if(isset(self::$_names[$class])) {
            $name self::$_names[$class];
        }
        else {
            $name = "Kandy"; // use some sort of default value
        }
    }

    static function setName($value) {
        $class = get_called_class();
        self::$_names[$class] = $value;
    }
}

方法三:__callStatic

这是迄今为止最方便的方法。但是,您需要有一个对象实例才能使用它(__get 和 __set 不能静态使用)。它也是最慢的方法(比其他两个慢得多)。我猜,既然你已经在使用静态属性,这已经是一个不可选项了。(如果此方法对您有用,那么如果您不使用静态属性可能会更好)

<?php
class SomeParent {

    const NAME_DEFAULT = 'Whatever defaults here';

    private static $_names = array();

    function __get($property) {
        if($property == 'name') {
            $class = get_called_class();
            if(isset(self::$_names[$class])) {
                return self::$_names[$class];
            }
            else {
                return static::NAME_DEFAULT;
            }
        }
        // should probably trigger some sort of error here
    }

    function __set($property, $value) {
        if($property == 'name') {
            $class = get_called_class();
            self::$_names[$class] = $value;
        }
        else {
            static::$property = $value;
        }
    }
}
于 2010-05-02T16:02:05.387 回答
0

比 Reece45 的回答更进一步,您可以使用以下方法获取数组的值。

<?php
class MyParent {
    public static $config = array('a' => 1, 'b' => 2);

    public static function getConfig() {
        $ret = array();
        $c = get_called_class();
        do {
            $ret = array_merge($c::$config, $ret);
        } while(($c = get_parent_class($c)) !== false);
        return $ret;
    }
}

class MyChild extends MyParent {
    public static $config = array('a' => 5, 'c' => 3, 'd' => 4);
    public function myMethod($config) {
        $config = array_merge(self::getConfig(), $config);
    }
}

class SubChild extends MyChild {
    public static $config = array('e' => 7);
}

var_export(MyChild::getConfig());
// result: array ( 'a' => 5, 'b' => 2, 'c' => 3, 'd' => 4, )

$mc = new MyChild();
var_export($mc->myMethod(array('b' => 6)));
// result: array ( 'a' => 5, 'b' => 6, 'c' => 3, 'd' => 4, )

var_export(SubChild::getConfig());
// result: array ( 'a' => 5, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 7, ) 
于 2015-12-04T23:41:27.097 回答
0

对于那些最终来到这里想知道“WTF PHP”的人来说,这种行为似乎有几个原因以及为什么保留它,尽管很奇怪:

  1. 静态属性将始终使用相同的内存引用,就像静态变量一样(来源
  2. 在类和子类之间共享相同的引用(
  3. 它似乎在其他一些情况下很有用,所以它不是一个“完整的”错误,只是未记录的行为。如果它得到“修复”,则会导致与以前工作代码的兼容性问题(向后兼容中断)。

不过还有两个问题:

  • 为什么后期静态绑定不会改变这一点:可能与#1有关
  • 为什么我们看到的那个缺点没有在文档页面中解释……嗯,那是PHP,对吧?
于 2021-06-05T02:51:29.767 回答