用于扩展子类的特征

时间:2016-11-30 14:02:35

标签: php oop traits

我有以下课程和特点:

class BasicModel {
   public function update() { /* some code */ }
}

class Task extends BasicModel {
   use TagTrait;
}

class User extends BasicModel {}

trait TagTrait {
   public function writeTag() { /* some code */ }
}

BasicModel-Class正在扩展Task和User(以及更多)。任务可以使用TagTrait定义一个函数来为每个使用类型写入标签。用户无法使用TagTrait。目标应该是,如果我在Task上调用update(),那么也应该调用trait来完成标记工作。我知道两种可能的方法。我可以覆盖Task中的update-function来调用writeTag函数,或者我必须检查BasicModel的update(),无论扩展类是否使用TagTrait,如果是,则调用writeTag-method。第一种方式并不是很聪明,因为我要多次做同样的工作。第二种方式对我来说也不是很好,但我不知道更好的方法。有什么建议吗?

2 个答案:

答案 0 :(得分:1)

有点难看,但可以合并,可以覆盖

class BasicModel {
    private static $updateMethods = [];
    public final function update() {
        echo "Start update\n";
        $c = get_class($this);
        if ( !array_key_exists($c,self::$updateMethods) ) {
          self::$updateMethods[$c] = preg_grep('/^_traitUpdate_/', get_class_methods($this));
        }
        foreach (self::$updateMethods[$c] as $m ) {
            $this->$m();
        }
    }
    protected function _update() { echo "Update Basic\n";}
}

class Task extends BasicModel {
    use TagTrait;
}

class User extends BasicModel {
}

class OtherTaggable extends BasicModel {
    use TagTrait,NoteTrait;
}

class TaskChild extends Task {
    use TagTrait;
    protected function _update() { echo "Update TaskChid overwriten\n";}
}

trait TagTrait {
    public function writeTag() { /* some code */ }

    public function _traitUpdate_TagTrait() { echo "TagTrait update\n"; }
}

trait NoteTrait {
    public function writeNote() { /* some code */ }

    public function _traitUpdate_NoteTrait() { echo "NoteTrait update\n"; }
}



$U = new User();
$T = new Task();
$O = new OtherTaggable();
$OC= new TaskChild();

$U->update();
echo "-\n";
$T->update();
echo "-\n";
$O->update();
echo "-\n";
$OC->update();

答案 1 :(得分:0)

您可以通过撰写

来实现它
class BasicModel {
   public function update() { echo 'Update'; }
}

class Tag {
   public function writeTag() { echo 'Write';  }
}

abstract class TaggingModel {
    private $model;
    private $tag;

    public function __construct(BasicModel $model, Tag $tag) {
        $this->model = $model;
        $this->tag = $tag;
    }

    public function update() { 
        $this->model->update();
        $this->tag->writeTag();
    }
}

class User extends BasicModel {};
class Task extends TaggingModel {}

// Prints `Update`
$user = new User();
$user->update();

// Prints `Update Write`
$task = new Task(new BasicModel(), new Tag());
$task->update();

限制是BasicModel update方法必须关联它自己的属性。

如果我们想跳过上述限制,我们可以实现组合和继承的组合:

class BasicModel {
   public function update() { echo 'Update'; }
}


class Tag {
   public function writeTag() { echo 'Write';  }
}


class TaggingModel extends BasicModel {
    public function __construct(Tag $tag) {
        $this->tag = $tag;
    }

    public function update() {
        parent::update();
        $this->tag->writeTag();
    }
}

class User extends BasicModel {};
class Task extends TaggingModel {}

// Prints `Update`
$user = new User();
$user->update();

// Prints `Update Write`
$task = new Task(new Tag());
$task->update();
相关问题