如何遍历孩子的私人领域?

时间:2017-07-05 13:07:48

标签: php oop inheritance iteration abstract-class

阅读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:重新提出问题,因为似乎存在误解

2 个答案:

答案 0 :(得分:1)

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

  2. private限制了具体课程的可见性 - 使用protected 代替。

  3. 在我看来,您只需要代码重用。你可以在这个casse中找到特征 - 特征成为一个类的一部分,你可以迭代私有字段。

    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());
    

答案 1 :(得分:0)

正确的解决方案是将基类implements声明为JsonSerializable接口,并在所有子类中实现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());

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