duancong2160 2011-03-01 04:18
浏览 34
已采纳

是否可以扩展对象的功能或将方法导入PHP中的对象?

I am facing a serious design problem that is driving me crazy. I think it can only be solved with multiple inheritance or something. So here is what I want to do:

Say I have a basic user class called OrdinaryUser defined in this way:

class OrdinaryUser
{
 private $id,$name;

 public function __construct($id)
 {
  $this->id = $id;
  $this->name = fictionalDB::getUserNameById($id);
 }

 public function getName()
 {
  return $this->name;
 }

 public function getId()
 {
  return $this->id;
 }

}

And I have a subclass called AdminUser with additional functionality:

class AdminUser extends OrdinaryUser
{
 public function deleteUser($id)
 {
  echo "Deleting user where id=$id";
 }
}

The problem: What if I have already instantiated an object of type "OrdinaryUser" and want to make it into an AdminUser object on-the-fly? Is there a way of "extending objects" so to avoid instantiating a subclass and having to re-populate the new object's fields with the same data?

Another related problem: I might have many other categories of users defined later, each having their own unique bahaviour, but always a basic one, and it wouldn't make sense to create a hierarchy in this case because most times one type of object should not be inheriting methods from the other type, although it might be desirable to have additional functionality from one type being "imported" into the other dinamically.

  • 写回答

4条回答 默认 最新

  • douzhong5902 2011-03-01 08:44
    关注

    Sounds like the Decorator Pattern may help you

    <?php
    /*
       an interface to ensure we only decorate Users
       and possibly some of the most common methods that all users have
       so that we don't always suffer the overhead of the magic __call method
    */
    interface User
    {
        public function getId();
        public function getName();
    }
    
    class OrdinaryUser implements User
    {
        private $id,$name;
    
        public function __construct($id)
        {
            $this->id = $id;
            $this->name = fictionalDB::getUserNameById($id);
        }
    
        public function getName()
        {
            return $this->name;
        }
    
        public function getId()
        {
            return $this->id;
        }
    
    }
    
    /*
       There aren't any abstract methods in this class
       but it is declared abstract because there is no point in instantiating one
    */
    abstract class UserDecorator implements User
    {
        protected $user;
    
        public function __construct( User $user )
        {
            $this->user = $user;
        }
    
        public function getId()
        {
            return $this->user->getId();
        }
    
        public function getName()
        {
            return $this->user->getName();
        }
    
        /*
           Any methods that aren't implemented by this type of
           user are dealt with by the decorated user
        */
        public function __call( $method, $arguments )
        {
            return call_user_func_array( array( $this->user, $method ), $arguments );
        }
    }
    
    class AdminUser extends UserDecorator
    {
        /*
           Add any methods that are particular to this type of user
        */
        public function addedMethod()
        {
            // do AdminUser type stuff
            return "doing added method stuff
    ";
        }
    
    }
    
    class FooUser extends UserDecorator
    {
        public function foo()
        {
            // do some foo
            return "doing fooness
    ";
        }
    }
    
    // just for testing
    class fictionalDB
    {
        public static function getUserNameById( $id )
        {
            $db = array(
                1 => 'Peter',
                2 => 'Paul'
            );
            return $db[$id];
        }
    }
    
    
    $user = new OrdinaryUser( 1 );
    echo $user->getName();    // Peter
    
    // make Peter into an AdminUser
    $user = new AdminUser( $user );
    
    // and also add some fooness
    $user = new FooUser( $user );
    echo $user->addedMethod(); // doing added method stuff
    echo $user->foo();         // doing fooness
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示