方法不会在其范围之外更改对象数组

Method doesn't change object array outside it's scope

据我所知,问题在于范围界定。

在方法 demo() 中,我正在调用方法 removeElement() 从数组中删除一个元素。

问题是当 removeElement() 方法从数组中删除士兵时,它只在该方法的范围内被删除,当我在 $this->removeElement(); 行之后的 demo() 方法中检查该数组时,数组保持不变.

我试过 return $elements 数组 removeElement() 方法,但这也无济于事,在这种情况下,它 return 只是数组而不是整个数组更新对象。

我已将问题简化为 this minimum example:

class Foo
{
    private array $elements = [];

    public function __construct(int $howMany)
    {
        for ($i = 0; $i < $howMany; $i++) {
            $this->elements[] = random_int(1, 100);
        }
    }


    public function getElements(): array
    {
        return $this->elements;
    }
}

class Demo
{
    public Foo $foo;

    public function __construct(int $howMany)
    {
        $this->foo = new Foo($howMany);
    }

    public function demo(): void
    {
        echo "\nWe start with ", count($this->foo->getElements()), " soldiers in $foo->elements\n"; 
        $this->removeElement();

        echo "\nWe have ", count($this->foo->getElements()), " soldiers in $foo->elements\n"; 
    }

    private function removeElement(): void
    {
        $elements = $this->foo->getElements();
        array_splice($elements, 2, 1);
        echo "\nWe have ", count($elements), " soldiers in local $elements\n"; 

    }
}

$init = random_int(4,10);
$demo = new Demo($init);
$demo->demo();

$remaining = count($demo->foo->getElements());

if ($init-1 !== $remaining) {
    throw new UnexpectedValueException('Wrong number of elements, application is broken');
}

输出:

We start with 10 soldiers in $foo->elements

We have 9 soldiers in local $elements

We have 10 soldiers in $foo->elements

Fatal error: Uncaught UnexpectedValueException: Wrong number of elements, application is broken in /in/3cnhl:54
Stack trace:
#0 {main}
  thrown in /in/3cnhl on line 54

Process exited with code 255.

我希望 $foo->elements 在经过 Demo::removeElement() 之后少一个元素。

该数组未按引用 return 编辑,因此未“就地”更改。这与 OOP 和 classes 无关,它是对函数和 return 值如何工作的基本理解。

基本上,你有三个选择

  • 在你的Fooclass中公开一个setElements(array $elements)。您可以在 removeElement() 方法中调用它。 (看到它工作 here

    private function removeElement(): void
      {
          $elements = $this->foo->getElements();
          array_splice($elements, 2, 1);
    
          echo "\nWe have ", count($elements), " soldiers in local $elements\n"; 
    
          $this->foo->setElements($elements);
      }
    
  • 既然你想从外部改变Foo::elements的内容,你也可以把属性变成public。 public array $elements;,并完全摆脱 getElements()。看到它工作 here.

  • getElements() return 作为参考,这就是您认为正在发生的事情。对我来说似乎有点矫枉过正,但这将是一个简单的“修复”。

    public function &getElements():array {
          return $this->elements;  
    }
    // and remember to access the dereference the return when using it:
    // $elements = & $this->foo->getElements();
    

    看到它有效here