【问题标题】:Method doesn't change object array outside it's scope方法不会在其范围之外更改对象数组
【发布时间】:2021-11-27 13:01:14
【问题描述】:

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

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

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

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

我已将问题简化为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-&gt;elements 在经过Demo::removeElement() 之后会少一个元素。

【问题讨论】:

    标签: php arrays class oop


    【解决方案1】:

    数组不是通过引用返回的,所以它没有“就地”改变。这与 OOP 和类无关,它是对函数和返回值如何工作的基本理解。

    基本上,你有三个选择

    • 在您的 Foo 类中公开 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 array $elements;,并完全摆脱 getElements()。看到它工作here

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

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

      看到它在工作here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-25
      • 2013-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多