对于我如何重新排列此代码以使所需输出正常工作,有人会有任何建议吗?我希望子类能够更新任何父类变量,以便循环中的下一个子类具有更新的变量。
class Foo {
protected $x = 0;
public function __construct() {
}
public function run() {
foreach (array(1, 2) as $id) {
$class_name = 'Bar' . $id;
$b = new $class_name();
$b->add();
}
}
public function getX() {
return $this->x;
}
}
class Bar1 extends Foo {
public function __construct() {
parent::__construct();
}
public function add() {
$this->x++;
}
}
class Bar2 extends Foo {
public function __construct() {
parent::__construct();
}
public function add() {
$this->x++;
}
}
$f = new Foo();
$f->run();
echo $f->getX(); # desired output should be 2
更新
我很抱歉这个令人困惑的问题但是我甚至在弄清楚如何问这个问题时遇到了麻烦。我真正的问题是我有一个非常大的,不断增长的课程我想要将每个方法分解为自己的类。以下是我目前正在使用的一小部分课程样本。父类不需要访问更新的变量,只需要子类,并且在这个例子中它们可以访问。但这不是我想要实现的目标。我是,但只是个别儿童班。
class Foo {
protected $x = 0;
public function __construct() {
}
public function run() {
$b = new Bar();
foreach (array(1, 2) as $id) {
$method_name = 'Bar' . $id;
$b->$method_name();
}
echo $b->getX(); # outputs 2
}
public function getX() {
return $this->x;
}
}
class Bar extends Foo {
public function __construct() {
parent::__construct();
}
public function Bar1() {
$this->x++;
}
public function Bar2() {
$this->x++;
}
# thousands of lines more and ever growing... 7,500+
}
更新2
这是另一个可行的版本,但对我来说似乎很奇怪..这会不会比静态版本更好?
class Foo {
public $x = 0;
public function __construct() {
}
public function run() {
foreach (array(1, 2) as $id) {
$class_name = 'Bar' . $id;
$c = new $class_name($this);
$c->add();
}
}
public function getX() {
return $this->x;
}
}
class Bar1 extends Foo {
private $foo;
public function __construct($foo) {
$this->foo = $foo;
}
public function add() {
$this->foo->x++;
}
}
class Bar2 extends Foo {
private $foo;
public function __construct($foo) {
$this->foo = $foo;
}
public function add() {
$this->foo->x++;
}
}
$f = new Foo();
$f->run();
echo $f->getX(); # outputs 2
答案 0 :(得分:1)
你遗漏的东西很简单:一个类是蓝图,你在类中声明的属性不作为类的一部分存在,而是:它们存在于你创建的各个实例中。
$x
中存在的Foo
属性完全独立于Bar
,Bar2
或Foo
的任何其他实例中存在的任意数量的属性可能在任何特定时间都存在。
如果要共享状态,则需要一些与实例生命周期无关的内容。在创建实例之前存在的东西,并且在实例是GC之后不会消失。基本上,您正在寻找static
财产。
class Foo
{
protected static $x = 0;
public function run()
{
foreach (array(1, 2) as $id) {
$class_name = 'Bar' . $id;
$b = new $class_name();
$b->add();
}
}
public function getX()
{
return static::$x;
}
}
class Bar1 extends Foo
{
public function add()
{
static::$x++;
}
}
class Bar2 extends Bar1
{}//no need to re-implement add...
那将有效
请注意,依靠静力学通常被认为是不好的做法。静力学引入了全球状态,在这样的情况下,他们最终会让你感到悲伤......考虑一下:
function runFoo($times = 1)
{
$foo = new Foo;
while ($times-- > 0) {
$foo->run();
}
return $foo->getX();
}
$first = runFoo();
$second = runFoo(2);
$third = runFoo(123);
现在没有运行它,尝试预测输出......
答案 1 :(得分:0)
也许我不理解你的问题,但你不能通过实例化孩子来增加主要课堂的$ x,因为他们有自己的$ x。
我的意思是,您创建的每个孩子都以$ this-> x == 0开头,最后是$ this-> x == 1(对于一次调用add()),并且永远不会更改OBJECT的属性,它们在循环中创建它们。
答案 2 :(得分:0)
我猜你有很多不同的方法可以进行某种计算。
如何让一个对象为每个计算器进行计算?
<?php
interface Calculator {
public function getTotal();
public function calculate();
}
class PlusOne implements Calculator
{
protected $x;
public function __construct($x)
{
$this->x = $x;
}
public function getTotal()
{
return $this->x;
}
public function calculate()
{
$this->x++;
}
}
class PlusTwo extends PlusOne
{
public function calculate()
{
$this->x = $this->x + 2;
}
}
class ItemsCalculator implements Calculator
{
protected $x = 0;
protected $items;
public function __construct($items)
{
$this->items = $items;
}
public function getTotal()
{
return $this->x;
}
public function calculate()
{
foreach($this->items as $item) {
$item->calculate();
$this->x = $this->x + $item->getTotal();
}
}
}
$itemsCalculator = new ItemsCalculator([new PlusOne(0), new PlusTwo(0)]);
$itemsCalculator->calculate();
echo $itemsCalculator->getTotal();
输出:
3
或者,您可以将总实例传递给每个计算器:
class Total
{
public $x;
}
class Plus1
{
protected $total;
public function __construct(Total $total)
{
$this->total = $total;
}
public function calculate()
{
$this->total->x++;
}
}
class Plus2 extends Plus1
{
public function calculate()
{
$this->total->x = $this->total->x + 2;
}
}