duanci9305 2012-11-14 19:07
浏览 64
已采纳

一般PHP / OOP策略 - 如何在嵌套对象之间进行通信

When using nested objects (ObjTwo as a property of objOne):

$objOne->property = new ObjTwo($objOne);

What's the best way to communicate? Here are a few methods I can think of:

Using specific get/set methods

class ObjTwo {
    __construct($objOne){
        $prop1 = $objOne->get_prop1(); 
        // do something with prop1
        $prop2 = $objOne->get_prop2();
        // do something with prop2

        // ... Having to write all these out is kind of a pain
        //     if you're going to have 20+ vars, and there's no
        //     easy way to loop through them.
    }
}

The problem: Writing these out line by line, and having to update it when I add new properties.

I know that having a get/set method for each property is recommended, however I'd really like to loop through the data...

How about get_object_vars()

class ObjTwo {
    __construct($objOne){
        extract(get_object_vars($objOne));
        // do something with the vars
    }
}

The problem: This method bypasses the ability to use getter/setter methods, and each property would have to be public to be accessible.

Dynamic getter/setter method calls

Another way I have considered is to create an array of fields, and have a strict policy of naming the getter/setter methods:

class ObjTwo {
    __construct($objOne){
        $prop_array = array('prop1', 'prop2', 'prop_three');
        $values = array();
        foreach ($prop_array as $prop){
            $values[$prop] = $objOne->get_{$prop}();
        }
    }
}

The problem: Every time I add a new property, I have to make sure to name the get_method() correctly, and update the $prop_array.

Anyone have any better solutions? Maybe just building an array of data?:

$objOne->property = new ObjTwo($objOne->get_data());

I like this solution

Having thought this through, here's a little clarification: I'm not trying to just make identical copies from parent to child or vice-versa - I edited the above examples to show that a little better. It's more just the idea of passing a subset of the object's data from one place to another.

Instead of having to write:

$first_name = $this->member->get_first_name();
$last_name = $this->member->get_last_name();
$email = $this->member->get_email();
$display_name = $this->member->get_display_name();
// etc... and
$this->member->set_first_name($first_name);
$this->member->set_last_name($last_name);
$this->member->set_email($email);
$this->member->set_display_name($display_name);
// etc..

How about having a $this->member->get_fields('first_name', 'last_name', 'email', 'display_name'); method? I don't like having to remember the field names exactly (fname, f_name, first_name, etc), so you could use class constants:

$data = $this->member->get_fields(array(
    Member::FIRST_NAME, Member::LAST_NAME, Member::EMAIL, Member::DISPLAY_NAME
));

This way, I can loop through the returned data.

foreach ($data as $key=>$value) // ...

And setting the fields...

$this->member->set_fields(array(
    Member::FIRST_NAME => $first_name,   //  THE BIG ADVANTAGE HERE:
    Member::LAST_NAME => $last_name,     //  These field keys auto-complete
    Member::EMAIL => $email,             //  so you don't have to remember them!
    Member::DISPLAY_NAME => $display_name,
    // etc...
));

Still thinking this through... any thoughts?

  • 写回答

2条回答 默认 最新

  • dongtang5057 2012-11-14 20:45
    关注

    I think you're asking the wrong question. Furthermore I think it would only be possible to really help, if you provided a real example instead of those pseudo examples. Every real situation is different with regard to the proper solution.

    Generally all your proposals smell. It seems that what you need is not injection but inheritance. If your 'child' class really needs access to all or most of the properties of another class, it seems it should extend that class.

    The parts of your software should know as little as possible about each other. In your comment you mention that you have a Member class and a Form class. I don't know why any of them should know anything about the other at all.

    Furthermore you seem to be under the impression that you need to map every property to a property in the new class. Why? If you pass an instance of a class into another class via custructor (= dependency injection) then you can map that instance to a property and then access all properties of the injected instance via that instance. No mapping needed.

    class Consumer
    {
        private $injectedClass;
    
        function __construct($injectedClass)
        {
            $this->injectedClass = $injectedClass;
        }
    
        public function someFunction()
        {
            //do something by using any property of the injected class
            $this->injectedClass->getProperty();
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记