抽象父类中的 PHP 静态变量

发布于 2024-10-29 05:54:48 字数 621 浏览 1 评论 0原文

包含问题的快速代码:

abstract class ClassParent {
    public static $var1 = "ClassParent";
}

class ClassChild1 extends ClassParent{
    public static function setvar1(){
        ClassChild1::$var1 = "ClassChild1";     
    }
}

class ClassChild2 extends ClassParent{
    public static function setvar1(){
        ClassChild2::$var1 = "ClassChild2";
    }
}


ClassChild1::setvar1();

echo ClassChild2::$var1;
// Returns "ClassChild1". Shouldn't this still be "ClassParent"?

我假设以上是预期行为,而不是 PHP 错误。在这种情况下,我如何在父类中声明一个静态变量,该变量将为子类单独处理。换句话说,我希望每个儿童班级都有单独的静态值。我必须在子类中专门声明静态变量还是有其他方法?

谢谢!

Quick code with the question included:

abstract class ClassParent {
    public static $var1 = "ClassParent";
}

class ClassChild1 extends ClassParent{
    public static function setvar1(){
        ClassChild1::$var1 = "ClassChild1";     
    }
}

class ClassChild2 extends ClassParent{
    public static function setvar1(){
        ClassChild2::$var1 = "ClassChild2";
    }
}


ClassChild1::setvar1();

echo ClassChild2::$var1;
// Returns "ClassChild1". Shouldn't this still be "ClassParent"?

I am assuming that the above is expected behaviour and not a PHP bug. In that case, how could I declare a static variable in the parent class which will be handled separately for the child classes. In other words, I want to have separate static values PER CHILD CLASS. Must I declare the static variable specifically in the child classes or is there perhaps another way?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

樱花坊 2024-11-05 05:54:48

编辑:经过进一步调查,我认为您所要求的并不是直接可能的,即使使用后期静态绑定也是如此。事实上,我有点惊讶。

此问题的答案提供了一些解决方法。

原始答案:


在父类中,如果您以以下形式引用静态变量:

self::$var

它将在所有继承的类中使用相同的变量(因此所有子类仍将访问父类中的变量)。

这是因为 self 关键字的绑定是在编译时而不是运行时完成的。

从 PHP 5.3 开始,PHP 使用 static 关键字支持后期静态绑定。因此,在您的类中,使用以下方式引用变量:

static::$var

并且“static”将在运行时解析为子类,因此每个子类都会有一个单独的静态变量。

EDIT: On further investigation, I think what you're asking is not directly possible, even with late static binding. Actually, I am a little surprised.

The answer to this question provides some workarounds.

Original answer:


In a parent class, if you refer to a static variable in the form:

self::$var

It will use that same variable in all inherited classes (so all child classes will be still accessing the variable in the parent class).

This is because the binding for the self keyword is done at compile-time, not run-time.

As of PHP 5.3, PHP supports late static binding, using the static keyword. So, in your classes, refer to the variable with:

static::$var

And 'static' will be resolved to the child class at run-time, so there will be a separate static variable for each child class.

泪是无色的血 2024-11-05 05:54:48

感谢您提出这个问题!我遇到了一些无法跟踪的问题,这帮助我解决了它们。 :)

您可能有兴趣知道针对此行为有一个错误报告其中包括解决方法。在你的情况下,这将是:

class ClassChild1 extends ClassParent{
    public static function setvar1(){
        $tmp = 'x';
        static::$var1 =& $tmp; // break reference
        // and now this works as expected: (changes only ClassChild1::$var1)
        static::$var1 = "ClassChild1";     
    }
}
// do the same in ClassChild2...

丑陋极了,我同意 - 但 PHP 以这种方式按预期工作,而且它没有副作用。

在我看来,这确实是一个非常可疑(且记录不足)的“功能” - 希望他们有一天能改变它。

Thanks for this question! I had some problems I couldn't track and this has helped me solve them. :)

You might be interested to know that there is a bug report for this behavior which includes the workaround. In your case this would be:

class ClassChild1 extends ClassParent{
    public static function setvar1(){
        $tmp = 'x';
        static::$var1 =& $tmp; // break reference
        // and now this works as expected: (changes only ClassChild1::$var1)
        static::$var1 = "ClassChild1";     
    }
}
// do the same in ClassChild2...

Ugly as hell, I agree - but PHP works as expected this way, plus it has no side effects.

This is indeed a very doubtful (and poorly documented) "feature" in my eyes - let's hope they change it someday.

梦情居士 2024-11-05 05:54:48

丑陋的解决方案,但它起作用。

我将静态$ var1移至需要在儿童课程中使用的特征。

这与在每个子类中宣布$ var1基本相同。
但是,使用此方法,您不会忘记声明$ var1。

trait Var1Trait
{
    public static $var1 = "ClassParent";

    protected function requiresVar1Trait()
    {
    }
}

abstract class ClassParent
{
    abstract protected function requiresVar1Trait(); // make sure that Var1Trait is used in child classes
}

class ClassChild1 extends ClassParent
{
    use Var1Trait;

    public static function setvar1()
    {
        ClassChild1::$var1 = "ClassChild1";
    }
}

class ClassChild2 extends ClassParent
{
    use Var1Trait;

    public static function setvar1()
    {
        ClassChild2::$var1 = "ClassChild2";
    }
}


ClassChild1::setvar1();

echo ClassChild2::$var1;
// Returns "ClassParent" as requested

Ugly solution, but it works.

I've moved static $var1 to a trait that is required to be used in child classes.

It is essentially the same as declaring $var1 in each child class.
However, using this method there is no chance you forget to declare $var1.

trait Var1Trait
{
    public static $var1 = "ClassParent";

    protected function requiresVar1Trait()
    {
    }
}

abstract class ClassParent
{
    abstract protected function requiresVar1Trait(); // make sure that Var1Trait is used in child classes
}

class ClassChild1 extends ClassParent
{
    use Var1Trait;

    public static function setvar1()
    {
        ClassChild1::$var1 = "ClassChild1";
    }
}

class ClassChild2 extends ClassParent
{
    use Var1Trait;

    public static function setvar1()
    {
        ClassChild2::$var1 = "ClassChild2";
    }
}


ClassChild1::setvar1();

echo ClassChild2::$var1;
// Returns "ClassParent" as requested
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文