PHP中不同的静态类实例

时间:2011-04-19 19:00:39

标签: php inheritance static

我有这段代码:

<?php
class Animal {
    static public $numLegs;

    public static function Walk() {
        return 'Takes a step with ' . self::$numLegs . ' legs.';
    }
}

class Dog extends Animal {
    public static function Init() {
        parent::$numLegs = 4;
    }
}

class Man extends Animal {
    public static function Init() {
        parent::$numLegs = 2;
    }
}

Dog::Init();
Man::Init();

echo 'The dog walks: ' . Dog::Walk(); //The dog walks: Takes a step with 2 legs.
echo 'The man walks: ' . Man::Walk(); //The man walks: Takes a step with 2 legs.
?>

问题是Animal :: $ numLegs变量对于两者都是相同的。我试图让Animal类不是静态的,但它给了我这个错误:

  

“致命错误:访问未声明的静态属性:Animal :: $ numLegs in ...”

我知道静态类无法实例化,但我想要的是为每个其他静态类(Man和Dog)设置不同的Animal :: $ numLegs'副本'。

我该怎么做?

感谢您的时间。

3 个答案:

答案 0 :(得分:3)

其他答案已经提到Late-Static-Binding作为问题的解决方案,而且确实是答案,但没有人正确实施,有些答案过于复杂。

静态变量旨在以前向方式用于所有实例或类的静态访问。因此,正如您在代码中所说,Man覆盖了Dog设置的值,因为您的静态变量是在父类“Animal”中设置的,因此每个子类都可以使用。 每个子类都具有访问权限,因此可以随时覆盖。

后期静态绑定通过允许您在子类而不是父类中具有静态变量的多个声明来解决此问题,但仍然允许父类对子类声明的静态变量进行操作。

这是你的代码,正确使用后期静态绑定。

<?php

class Animal {
    public static function Walk() {
        return 'Takes a step with ' . static::$numLegs . ' legs.'; //the 'static' keyword lets you operate on child classes' static vars
    }
}

class Dog extends Animal {

    static public $numLegs; //dog has its own static var

    public static function Init() {
        self::$numLegs = 4;
    }
}

class Man extends Animal {

    static public $numLegs; //man has its own static var

    public static function Init() {
        self::$numLegs = 2;
    }
}

Dog::Init();
Man::Init();

echo 'The dog walks: ' . Dog::Walk(); //The dog walks: Takes a step with 2 legs.
echo 'The man walks: ' . Man::Walk(); //The man walks: Takes a step with 2 legs.
?>

结果:

  

狗走路:4步   男人走路:走了一步   2条腿。

答案 1 :(得分:1)

前言:您需要使用PHP 5.3+才能使用我的示例。在PHP 5.3之前,这种东西实际上是不可能的。 Late Static Bindings的引入改变了这一点。 :)


您可以使用类常量来实现相同的所需继承。

<?php

class Animal {
    const NUM_LEGS = 4;

    public static function Walk() {
        return 'The ' . get_called_class() . ', takes a step with ' . static::NUM_LEGS . " legs.\n";
    }
}

class Dog extends Animal {}

class Man extends Animal {
    const NUM_LEGS = 2;
}

class Shark extends Animal {
    const NUM_LEGS = 0;
}

echo Dog::Walk();   // The Dog, takes a step with 4 legs
echo Man::Walk();   // The Man, takes a step with 2 legs
echo Shark::Walk(); // The Shark, takes a step with 0 legs

或者,如果您不想使用常量,您仍然可以使用变量。 :)

<?php

class Animal {
    public static $numLegs = 4;

    public static function Walk() {
        return 'The ' . get_called_class() . ', takes a step with ' . static::$numLegs . " legs.\n";
    }
}

class Dog extends Animal {}

class Man extends Animal {
    public static $numLegs = 2;
}

class Shark extends Animal {
    public static $numLegs = 0;
}

echo Dog::Walk();   // The Dog, takes a step with 4 legs
echo Man::Walk();   // The Man, takes a step with 2 legs
echo Shark::Walk(); // The Shark, takes a step with 0 legs

答案 2 :(得分:1)

您应该使用类继承。这是有原因的:让你的编码器更好,并简化事情。这是一个例子:

<?php
class Animal {
    protected $numLegs;
    protected $name;

    public function __construct()
    {
       $name = 'Animal';
    }

    public function Walk() {
        return 'The ' . $this->name . 'walks: Takes a step with ' . $this->$numLegs . ' legs.';
    }
}

class Dog extends Animal {
    public function __construct() {
        parent::___construct('Dog');
        $this->$numLegs = 4;
    }
}

class Man extends Animal {
    public function __construct() {
        parent::___construct('Man');
        $this->$numLegs = 2;
    }
}

class Turtle extends Animal {
    public function __construct() {
        parent::___construct('Turtle');
        $this->$numLegs = 4;
    }

    public function Walk() {
        return 'The ' . $this->name . 'walks: SLOWLY takes a step with ' . $this->$numLegs . ' legs.';
    }
}

$dog = Dog->Init();
$man = Man->Init();

echo $dog->Walk(); //The dog walks: Takes a step with 2 legs.
echo $man->Walk(); //The man walks: Takes a step with 2 legs.
?>

编辑:我还展示了如何使用这种方式创建一个新类并更改Walk()输出的文本而不更改任何其他类。