PHP中静态类的不同实例

发布于 2024-11-02 11:32:34 字数 866 浏览 0 评论 0原文

我有这样的代码:

<?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...”

我知道静态类无法实例化,但我想要的是有一个 Animal::$numLegs 的不同“副本”对于每个其他静态类(Man 和 Dog)。

我怎样才能做到这一点?

感谢您抽出时间。

I have this code:

<?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.
?>

The problem is that the Animal::$numLegs variable is the same for both. I've tried to make the Animal class not static, but it gives me this error:

"Fatal error: Access to undeclared static property: Animal::$numLegs in..."

I understand that static classes can't be instantiated, but what I want is to have a different 'copy' of the Animal::$numLegs for each of the other static classes (Man and Dog).

How can I do that?

Thanks for your time.

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

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

发布评论

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

评论(3

↘人皮目录ツ 2024-11-09 11:32:34

其他答案已经提到 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条腿。

Other answers have already mentioned Late-Static-Binding as the solution to your problem and it is indeed the answer, but nobody has implemented it correctly and some answers have been overly complex.

A static variable is intended to be available to all instances or static accesses of a class in forward-facing fashion. So, as you said in your code, Man was overwriting the value set by Dog because your static variable was set in the parent class, 'Animal', and so was available to each child class. Each child class has access and so can overwrite at any point.

Late static binding solves this by allowing you to have multiple declarations of your static variable in the child classes instead of the parent, but still allowing the parent class to operate on the static variable declared by the child class.

Here is your code, using late static binding properly.

<?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.
?>

And the result:

The dog walks: Takes a step with 4
legs.The man walks: Takes a step with
2 legs.

桃扇骨 2024-11-09 11:32:34

前言:您需要使用 PHP 5.3+ 才能使我的示例正常工作。在 PHP 5.3 之前,这种事情实际上是不可能的。 最新静态绑定的引入改变了这一点。 :)


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

<?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

Preface: You need to be using PHP 5.3+ for my example to work. Before PHP 5.3, this sort of stuff was not really possible. The introduction of Late Static Bindings changed that. :)


You can use class constants to achieve the same desired inheritance.

<?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

Alternatively, if you don't want to use a constant, you can still use a variable. :)

<?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
半山落雨半山空 2024-11-09 11:32:34

您应该利用类继承。它的存在是有原因的:让你的编码员变得更好并简化事情。这是一个示例:

<?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() 输出的文本,而不更改任何其他类。

You should make use of class inheritance. It is there for a reason: to make your coder nicer and to simplify things. Here is an example:

<?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.
?>

Edit: I have also shown how you can then use this way to create a new class and change the text outputted by Walk() without changing any other class.

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