3

I am trying to extend static class in PHP. What I am running into is that once I change the variable in one of the extend classes, all others classes are changes as well. This is what I am trying to do:

class Fruit{
    private static $name = Null;
    public static function setName($name){
        self::$name = $name;
        }
    public static function getName(){
        return self::$name;
        }
    } 

class Apple extends Fruit{};
class Banana extends Fruit{};

Apple::setName("apple");
Banana::setName("Banana");

echo Apple::getName();
echo Banana::getName();

I have read about late static binding and the keyword static::. But I cannot think of a way how to accomplish this without having to redeclare all Fruit's methods in both Apple and Banana.

I will be happy for any help

Thank You

Blujacker
  • 68
  • 7

2 Answers2

4

This works:

<?php

class Fruit{
    protected static $name = Null;
    public static function setName($name){
        static::$name = $name;
        }
    public static function getName(){
        return static::$name;
        }
    } 

class Apple extends Fruit{protected static $name;};
class Banana extends Fruit{protected static $name;};

Apple::setName("apple");
Banana::setName("Banana");

echo Apple::getName();
echo Banana::getName();

Unfortunately you need to re-declare the static properties you want to specialize, but your late static binding intuition was right :)

djfm
  • 2,317
  • 1
  • 18
  • 34
  • ... and that seems to be the only way if one doesn't want to mess with magic methods. BTW, declaring `$name` in `Fruit` class is not really needed here - but may be useful for readability. – raina77ow Apr 05 '14 at 21:05
  • 1
    @raina77ow You're right, but it may also be useful for child classes who do not want / need to specialize the property. – djfm Apr 05 '14 at 21:07
0

Although you should avoid such constructions, you could solve it quite nicely:

<?php

class Fruit {
    protected static $names;
    public static function setName($name)
    {
        self::$names[get_called_class()] = $name;
    }

    public static function getName()
    {
        return isset(self::$names[$key = get_called_class()]) ? self::$names[$key] : null;
    }
}

So basically you store the data in just a single class, but specific to the class the method was called on. You don't need static as $name is always part of self, but 5.3 is still required because get_called_class is also part of late static binding.

Joost
  • 10,333
  • 4
  • 55
  • 61
  • Thank You for the solution but I will rather stick to what @djfm suggested. Will work better for classes where there are more variables (fruit's color, flavour, ...). – Blujacker Apr 05 '14 at 21:18
  • I'm not keen on this solution as it means that `Fruit` is aware of the fact it is sub-classed. This is quite strongly linked to the question here: http://programmers.stackexchange.com/questions/219543/should-a-class-know-about-its-subclasses. It may not break Liskov's Substitution Principle, but certainly smells bad to me... – Rob Baillie Apr 05 '14 at 21:43
  • @Rob I most certainly agree, hence the first sentence of this answer. This approach is sometimes useful, although better design will avoid it. – Joost Apr 05 '14 at 22:08