PHP上的类实例?
我不知道它叫什么,我相信它是实例PHP上的类实例?,php,Php,我不知道它叫什么,我相信它是实例 class Monster { private $monsters = array(); public function __construct() { self::monsters[] = $this; } public function __destruct() { array_splice(self::monsters, array_search($this, self::monsters)
class Monster {
private $monsters = array();
public function __construct() {
self::monsters[] = $this;
}
public function __destruct() {
array_splice(self::monsters, array_search($this, self::monsters), 1 );
}
public static function getTotalHp() {
$total = 0;
foreach(self::monsters as $monster) {
$total += $monster->getHp();
}
return $total;
}
}
假设我们有一个“怪物”类。此类应包含“健康”值。在创建类时将其设置为“5”。它还应该包含每个怪物的唯一ID值
我会这样想:
$monster_1 = new Monster(); //sets monster ID to 1
$monster_2 = new Monster(); //sets monster ID to 2
$monster_3 = new Monster(); //sets monster ID to 3
$monsters = array();
$totalHP = 0;
foreach($monsters as $monster) {
$totalHP += $monster->getHp();
}
所以,假设我想计算所有怪物的总生命值
$totalHp = $monster_1->getHp() + $monster_2->getHp() + $monster_3->getHp();
它也可以工作,但是如果我添加一个名为$monster_4
的新怪物会怎么样呢。我必须手动将其添加到$totalHp计算中
我可以制作一个数组而不是$monster
变量,并用foreach计算$totalHp-但它看起来很奇怪
我不知道其他语言是如何做到的
有没有其他方法来归档这个
顺便说一句,我正试图弄明白“游戏”背后的逻辑。您创建了一个怪物类,每个怪物都使用这个类作为实例。我的解决方案肯定会起作用,但我不确定这是否是一种黑客式的归档方式。您可以使用一个对象作为怪物的容器,并使用它来跟踪您:
class MonsterContainer
{
private $monsters = array();
public function __construct()
{
// do stuff
}
public function addMonster(Monster $monster)
{
$this->monsters[] = $monster;
}
public function totalMonstersHP()
{
$hp = 0;
foreach ($this->monsters as $monster)
{
$hp += $monster->getHp()
}
return $hp;
}
}
$monster_1 = new Monster();
$monster_2 = new Monster();
$monster_3 = new Monster();
$container = new MonsterContainer();
$container->addMonster(monster_1);
$container->addMonster(monster_2);
$container->addMonster(monster_3);
echo $container->totalMonstersHP();
首先,它们被称为对象或实例,就像在面向对象的编程中一样 其次,没有什么能阻止你创建一个怪物阵列(看起来并不奇怪):
$monsters = array(
new Monster(),
new Monster(),
new Monster(),
new Monster()
);
foreach($monsters as $monster) {
$totalHP += $monster->hp;
}
关于唯一ID,这应该是怪物工厂的责任,也就是说,怪物应该分配一个ID,它不应该分配给它自己,而应该分配给它。在创建怪物时,类似这样的操作:
new Monster(4); //ID is 4
谁跟踪它?其他人,而不是怪物。我支持alexn,使用数组存储类实例(是的,这是正确的术语)非常好
然后,您可以使用foreach
计算总HP。创建MonstersCollection类,该类将包含方法getNewMonster()
和getTotalHP()
伪代码:
class MonstersCollection
{
private $Monsters;
public function getNewMonster()
{
$Monster=new Monster();
$this->monsters[]=$Monster;
return $Monster;
}
//and you know how to write method to get total HP :)
}
您可以创建一个$monsters
数组,如下所示:
$monster_1 = new Monster(); //sets monster ID to 1
$monster_2 = new Monster(); //sets monster ID to 2
$monster_3 = new Monster(); //sets monster ID to 3
$monsters = array();
$totalHP = 0;
foreach($monsters as $monster) {
$totalHP += $monster->getHp();
}
然后,每次您想要添加怪物时,都要执行以下操作:
$monsters[] = new Monster();
然后,您可以在阵列中循环以获得总生命值,如下所示:
$monster_1 = new Monster(); //sets monster ID to 1
$monster_2 = new Monster(); //sets monster ID to 2
$monster_3 = new Monster(); //sets monster ID to 3
$monsters = array();
$totalHP = 0;
foreach($monsters as $monster) {
$totalHP += $monster->getHp();
}
在循环之后,$totalHP
将包含您阵列中所有怪物的总生命值。也许您可以在同一怪物类中创建一个新类或函数
在构造函数中调用,每次创建类时
它调用一个增加的全局变量。创建一个助手类,该类包含一组怪物,可能是一个怪物团队类
class Monster {
...
}
class MonsterTeam {
private $_monsters = [];
public function addMonster(Monster &$monster) {
array_push($this->_monsters, $monster);
}
public function getTotalHp() {
$hp = 0;
foreach ($this->_monsters as $monster) {
$hp += $monster->getHp();
}
return $hp;
}
}
$team = new MonsterTeam();
$monsterA = new Monster();
$team->addMonster($monsterA);
$monsterB = new Monster();
$team->addMonster($monsterB);
echo "Total HP: " . $team->getTotalHp();
您可以创建观察者模式,该模式可以在Monster实例化时自动更新集中对象中的totalHp属性
但在怪物类中,更快/更简单的方法是这样的:
class Monster {
...
private $hp = 5;
private static $totalHp = 0;
...
public function getHp() {
return $this->hp;
}
public function __construct(...) {
...
self::totalHp += $this->getHp();
...
}
public function __destruct(...) {
...
self::totalHp -= $this->getHp();
...
}
...
public static function getTotalHp() {
return self::totalHp;
}
/**
* Provide negative number to reduce HP or positive to increase HP.
*/
public function alterHp($hp) {
$this->hp += $hp;
self::totalHp += $hp;
}
}
然后,要获得当前的HP总值,您必须在客户端代码中执行以下操作:
$totalHp = Monster::getTotalHp();
你可以创建一个收集工厂;它将负责创造新的怪物。将两个类融合在一起通常不是我的事情,但我喜欢这样一个事实,即我可以使构造函数私有:)
它使用两个静态变量(我想是glorified global),一个用于怪物id,另一个用于怪物集合,使用SplObjectStorage
需要迭代所有怪物的方法使用each()
方法,因此可以在类之外定义所需的任何逻辑
class Monster
{
private $id;
public $health;
private static $instances;
private static $nextid = 1;
// private constructor
private function __construct($id)
{
$this->id = $id;
$this->health = 5;
}
public static function create()
{
if (!self::$instances) {
self::$instances = new SplObjectStorage;
}
$o = new self(self::$nextid++);
self::$instances->attach($o);
return $o;
}
public static function remove($o)
{
if (!self::$instances) { return; }
self::$instances->detach($o);
}
// iterate over all objects
public static function each($cb)
{
if (!self::$instances) { return; }
foreach (self::$instances as $o) {
$cb($o);
}
}
}
小用法示例
$m1 = Monster::create();
$m2 = Monster::create();
$total_health = 0;
Monster::each(function(Monster $m) use (&$total_health) {
$total_health += $m->health;
});
echo "Total health: $total_health\n";
类跟踪其实例是很常见的
class Monster {
private $monsters = array();
public function __construct() {
self::monsters[] = $this;
}
public function __destruct() {
array_splice(self::monsters, array_search($this, self::monsters), 1 );
}
public static function getTotalHp() {
$total = 0;
foreach(self::monsters as $monster) {
$total += $monster->getHp();
}
return $total;
}
}
你可以用eval()
来做,但这会很麻烦。阵列似乎是你的最佳选择,我想说,随它去吧。不要使用eval(),永远不要。将所有怪物存储在阵列中是一个完美的解决方案。@OZ_u这就是为什么我说它会很有黑客味。@OZ_u经典的货物崇拜编程。如果你从来没有使用过脚本语言和编译语言的区别,那么你就犯了严重的错误。Meme编码和不理解用例(正确工作的正确工具)并不太专业。这就是方法!Maby类怪物扩展敌人
它违反了入侵。相同。这是一个全局变量。不是这样的。我已经更新了我的答案,以展示一种你们可能会觉得更吸引人的替代方式。所以,你们制作了一个奇特的数组?这不是一种优雅的方法,至少,你们需要将\u construct
设为私有,这样其他人就不能制造怪物了。@JuanMendes同意,在比约恩的答案中有更正确的代码-这里只是一个例子来说明这个想法。不,不要使用全局变量。计算ID不是Monster类的责任。与John Conde的回答相同,我对此投了赞成票,但它很脆弱,如果getHp()
发生变化怎么办?最好跟踪所有实例,并在调用getTotalHp时为所有实例调用getHp()
。这是一个快速代码示例。我不打算在这里实现整个应用程序。理想情况下,getHp()应该只作为$hp属性的getter。没有其他内容。现在totalHp仅在hp更改时更新。这确保了我们拥有精确的totalHp,而无需一次又一次地运行循环。我不知道怎么做。totalHp属性在整个程序执行过程中得到正确维护。我不会做任何循环或数组搜索来减慢程序的速度。@Matthieu:同意。更正。为什么通过引用传递对象?我认为这在物体中并不重要。这是一个正确的答案。您需要一个支持依赖项注入的集合对象,这样您就可以向组中添加各种不同的怪物。接下来移除引用指针,并将怪物
类指定为一个抽象类,由每种类型的怪物扩展。这个答案要求任何创建怪物的代码也可以访问最新团队
查看我的答案。我真的不明白