Question

I'm having the following problem:

<?php

/**
 * Mother class defining static methods/attribute
 */
class A
{
    public static $_greetings = 'Nothing';

    public static function hi()
        {
            $c = get_called_class();
            echo $c.' says '.$c::$_greetings.PHP_EOL;
        }

    public static function set($classname)
        {
            $c = get_called_class();
            $g = $classname::$_greetings;

            echo 'Setting '.$c.'::_greetings to '.$g.PHP_EOL;
            $c::$_greetings = $g;
        }
}

/**
 * Children using inherited static method
 */
class C1 extends A
{
    public function say() { self::hi(); }
}

class C2 extends A
{
    public function say() { self::hi(); }
}

/**
 * Data containers
 */
class D1
{
    public static $_greetings = 'Hello World!';
}

class D2
{
    public static $_greetings = 'Ola Chica!';
}

// ------------------------------------------------------------------------

/**
 * The great misunderstanding...
 */
C1::set( 'D1' );
C2::set( 'D2' );

$c1 = new C1();
$c2 = new C2();

$c1->say();
$c2->say();

echo C1::$_greetings.PHP_EOL;
echo C2::$_greetings.PHP_EOL;

In a few words A defines a method to print a static message $_greetings. This message is to be set using A::set( classname ) which takes in input the name of a class that contains a static parameter $_greetings too. Then come two children, defining their own method say() to say hi using the inherited static hi(). I would expect the output to be:

Setting C1::_greetings to Hello World!
Setting C2::_greetings to Ola Chica!
C1 says Hello World!
C2 says Ola Chica!
Hello World!
Ola Chica!

but instead I get:

Setting C1::_greetings to Hello World!
Setting C2::_greetings to Ola Chica!
C1 says Ola Chica!
C2 says Ola Chica!
Ola Chica!
Ola Chica!

and I'd like to understand why...!? Many thanks in advance for those who will take the time to understand the problem :)

Was it helpful?

Solution

I could find the answer here, even though the question wasn't phrased in the same way: PHP 5.3: Late static binding doesn't work for properties when defined in parent class while missing in child class

In my little example, the problem comes from the fact that apparently, unless specified otherwise (see below how), the storage for static variables is the same for a "family" of classes (that is, for mother and all children classes). To make sure each class gets its own storage, you just need to redeclare the same static variables in the child class, like so:

/**
 * Children using inherited static method
 */
class C1 extends A
{
    public static $_greetings;
    public function say() { self::hi(); }
}

class C2 extends A
{
    public static $_greetings;
    public function say() { self::hi(); }
}

Putting this back into the previous example, the output is exactly as expected:

Setting C1::_greetings to Hello World!
Setting C2::_greetings to Ola Chica!
C1 says Hello World!
C2 says Ola Chica!
Hello World!
Ola Chica!
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top