【问题标题】:How do I iterate through a child's private fields?如何遍历孩子的私有字段?
【发布时间】:2017-12-09 04:18:48
【问题描述】:

看完this question 我的问题的一个想法是在子类中实现该方法,例如:

class Child {
    private $childField = "Want to see";
    public $pubChildField = "Will see";

    public function method()
    {
        $assoc = []; // a associative array
        foreach ($this as $field => $value) {
            $assoc[$field] = doStuff($value);
        }
        return $assoc;
    }
}
var_dump((new Child())->jsonSerialize());

但是为此,我必须在每个子类中复制代码。为了可读性,我想将其重构为(已经存在的)parentClass,类似于:

abstract class parentClass {
    public function method()
    {
        $assoc = []; // a associative array
        foreach ($this as $field => $value) {
            $assoc[$field] = doStuff($value);
        }
        return $assoc;
    }
}
class Child extends parentClass {
    private $childField;
    public $pubChildField;
}
var_dump((new Child())->jsonSerialize());

foreach ($this as $k=>$v)get_object_vars() 都将从实例中获取公共字段。我需要获取它的私有字段,以便进行序列化。


编辑 1:错字抽象方法 - 我在想什么

编辑 2:阐明示例

编辑 3:重新提出问题,因为似乎存在误解

【问题讨论】:

  • obviously $this refers to the abstract method.... 不!!!! $this 指的是instance$this 从不引用一个类
  • 詹森,你为什么要这样做?
  • 这是 PHP 手册,其中包含 PHP 中的对象和类的基础知识:php.net/manual/en/language.oop5.basic.php。这里有更多关于对象继承的内容:php.net/manual/en/language.oop5.inheritance.php。我认为你应该仔细阅读它们。
  • 你可以使用get_object_vars(),但是,恕我直言,整个想法很糟糕,应该放弃。
  • 基类不应该知道扩展它的类。它甚至不应该关心它是否被扩展。

标签: php oop inheritance iteration abstract-class


【解决方案1】:
  1. 抽象类是关于抽象方法的,而不是继承的。我假设这些 与问题无关(否则将其设为普通默认/基类)。

  2. private 限制对具体类的可见性 - 使用 protected

在我看来,您只需要代码重用。在这种情况下,您可能会接触到特征 - 特征成为类的一部分,并且您可以迭代私有字段。

interface ArrayData {
    public function toArray(): array;
}

trait ToArray {
    public function toArray(): array {
        $assoc = []; // a associative array
        foreach ($this as $field => $value) {
            $assoc[$field] = $value;
        }
        return $assoc;
    }
}

class Foo implements ArrayData {
    use ToArray;

    private $childField = "Want to see";
    public $pubChildField = "Will see";
}

$foo = new Foo();

var_dump($foo->toArray());

【讨论】:

  • hm... 使用 protected 似乎是最干净的解决方案... 接受(即使它不能解决标题中提出的问题)
  • @S.Janssen 使用特征,您可以重用代码并迭代私有字段。也许这就是你要找的。​​span>
【解决方案2】:

正确的解决方案是声明基类implementsJsonSerializable接口,并在所有子类中实现JsonSerializable::jsonSerialize()方法。

您可以让它在基类中未实现以强制所有子类实现它,或者您可以在基类中为不需要序列化的子类提供默认实现 (return array();)。

每个类中的实现不应遍历对象属性列表。通常,并非所有对象属性都必须进行序列化,并且可序列化的属性也不是天生平等的。

abstract class parentClass implements JsonSerializable {

    // You can remove this default implementation
    // to force all children class implement the method
    public function jsonSerialize()
    {
        return array();
    }
}

class childClass extends parentClass {
    private $childField;
    public $pubChildField;

    public function jsonSerialize()
    {
        return array(
            'field1' => $this->childField,
            'field2' => base64_encode($pubChildField),
            // etc ...
        );
    }
}

var_dump((new Child())->jsonSerialize());

尝试编写更易于阅读和理解的代码。以后你会感谢自己的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多