PHP 中静态成员的继承

2022-08-30 12:37:46

在 PHP 中,如果在父类中定义了静态属性,则无法在子类中重写它。但我想知道是否有任何办法可以解决这个问题。

我正在尝试为其他人的(有点笨拙)函数编写一个包装器。所讨论的函数可以应用于许多不同的数据类型,但每种数据类型都需要不同的标志和选项。但在99%的情况下,每种类型的默认值就足够了。

如果这可以通过继承来完成,而不必每次都编写新函数,那就太好了。例如:

class Foo {
    public static $default = 'DEFAULT';

    public static function doSomething ($param = FALSE ) {
        $param = ($param === FALSE) ? self::$default : $param;
        return $param;
    }
}

class Bar extends Foo {
    public static $default = 'NEW DEFAULT FOR CHILD CLASS';
}

echo Foo::doSomething() . "\n"; 
// echoes 'DEFAULT'

echo Bar::doSomething() . "\n"; 
// echoes 'DEFAULT' not 'NEW DEFAULT FOR CHILD CLASS' 
// because it references $default in the parent class :(

答案 1

实际上,我认为这不是真的:你可以使用静态概率(你需要>=5.3 PHP)。但是,在对该静态属性进行折射时必须小心(这是原始代码中的错误),

您需要使用 static::$myStaticProperty 而不是使用 self::$myStaticProperty

self:: 将折射到当前类,因此,如果您位于继承的静态方法中,这将折射该类定义该方法的静态属性!使用引用关键字 static:: 时,将像$this一样 - 当您使用实例方法/propeties 时。

doSomething() 是示例中类 Bar 中继承的静态方法。由于您使用了 self:: 在那里,它将引用类 Foo 的静态属性。这就是为什么你没有看到任何区别的原因...尝试将 self:: 更改为 static::

下面是一个代码示例 - 我自己用它来测试这些东西。我们有静态属性/方法继承,覆盖和值更改 - 运行它,你会看到结果!

class A {

    // a static property - we will test override with it
    protected static $var = 'class A var - override';
    // a static property - we will test value overwrite with it
    protected static $var2 = 'class A var2 - value overwrite';


    public static function myStaticOverridePropertyTest() {
        return static::$var;
    }
    public static function myStaticValueOverwritePropertyTest() {
        return static::$var2;
    }

    /**
     * This method is defined only here - class B will inherit this one!
     * We use it to test the difference btw self:: and static::
     * 
     * @return string
     */
    public static function myStaticMethodTest() {
        //return self::getValue();
        return static::getValue();
    }

    /**
     * This method will be overwritten in class B
     * @return string
     */
    protected static function getValue() {
        return 'value from class A';
    }
}


class B extends A {

    // we override this inherited static property
    protected static $var = 'class B var - override';

    /**
     * This method is overwritten from class A
     * @return string
     */
    protected static function getValue() {
        return 'value from class B';
    }

    /**
     * We modify the value of the inherited $var2 static property
     */
    public static function modStaticProperty() {
        self::$var2 = 'class B - altered value! - value overwrite';
    }
}

echo ("-- testing class A:\n");
echo (A::myStaticOverridePropertyTest(). "\n");
echo (A::myStaticValueOverwritePropertyTest(). "\n");
echo (A::myStaticMethodTest(). "\n");

echo ("-- now testing class B:\n");
echo (B::myStaticOverridePropertyTest(). "\n");
echo (B::myStaticValueOverwritePropertyTest(). "\n");
echo ("  now invoking B::modStaticProperty()     .\n");
B::modStaticProperty();
echo (B::myStaticValueOverwritePropertyTest(). "\n");

echo ("-- now re-testing class A:\n");
echo (A::myStaticOverridePropertyTest(). "\n");
echo (A::myStaticValueOverwritePropertyTest(). "\n");
echo (A::myStaticMethodTest(). "\n");

这将输出:

-- 测试类 A:
类 A var - 覆盖
类 A var2 - 值覆盖
类 A
中的值 -- 现在测试类 B:
类 B var - 覆盖
类 A var2 - 值覆盖
现在调用 B::modStaticProperty() ...
B类 - 改变价值!- 值覆盖
-- 现在重新测试类 A:
类 A var - 覆盖
类 B - 更改的值! - 值覆盖
类 A

的值 在这里,您可以看到覆盖的值和仅覆盖值的静态属性之间的区别...看看我用粗体标记的输出行!当我们调用类 B 的 modStaticProperty() 时,它也更改了类 A 中该静态变量的值。由于该静态属性是继承的,因此未被覆盖!想想吧。。。


答案 2

即将发布的 PHP 5.3.0 版本包含后期静态绑定,这可能会有所帮助。使用此功能,您可以在静态方法中使用静态变量,并让后期静态绑定负责查找“正确”的方法。

class Foo {
    public static function getDefault() {
        static $default = 'DEFAULT';
        return $default;
    }
    public static function doSomething ($param) {
        $default=static::getDefault(); // here is the late static binding
        $param = ($param === FALSE) ? $default : $param;
        return $param;

    }
}

class Bar extends Foo {
     public static function getDefault() {
        static $default = 'NEW DEFAULT FOR CHILD CLASS';
        return $default;
    }
}

推荐