【问题标题】:PHP : add methods calling $this to existing classesPHP:将调用 $this 的方法添加到现有类
【发布时间】:2015-02-02 10:44:51
【问题描述】:

我有一个容器类:

class ContainerClass {
    var $subobj;
    var $myName;

    function __construct($val, $name)
    {
        $this->myName = $name;
        $this->subobj = new ItemClass ($val);
    }

    function getItem()
    {
        return ($this->subobj);
    }
}

还有一个班级:

class ItemClass {
    var $value;

    function __construct($val)
    {
        $this->value = $val;
    }
}

这两个类是一个假设库的成员,只需使用include 调用即可在许多项目中使用。

在我的项目中,我需要做一些具体的展示,所以对于每个项目,我想在不修改库源代码的情况下,添加这样的方法(带有项目特定的内容) :

项目 1

对于ContainerClass

function getDisplay () {
   return ($myName . " : " . $this->subobj->getDisplay());
}

对于ItemClass

function getDisplay () {
   return (/* some display */ $this->value);
}

function getDisplayAlone () {
   return (/* some display */"<DIV>" .  $this->value . "</DIV>");
}

项目 2

对于容器类:

function getDisplay () {
   if ($this->value == 5) return ($myName . " : " . $this->subobj->getDisplay());
   return ("No luck !");
}

对于ItemClass

function getDisplay () {
   return (/* some display */"Go to hell !");
}

function getDisplayAlone () {
   return (/* some display */"<DIV>What's up doc ?</DIV>");
}

并且能够从每个项目的主 php 文件中调用这些:

include "mylibrary.php";
$obj = new ContainerClass (10, "Me");
$obj->getDisplay();
$obj->getItem()->getDisplayAlone();

我发现了许多向类和对象添加方法的技巧和窍门,但它们要么不适用于 php5,要么不允许在方法中使用 $this,要么根本不起作用。

有人可以帮我实现吗?

【问题讨论】:

    标签: php class dynamic methods dynamic-programming


    【解决方案1】:

    假设这将是您的库类:

    class ContainerClass 
    {
        protected $subobj; //Must be protected to be accessable for the child classes
        protected $myName; //Must be protected to be accessable for the child classes
    
        function __construct($val, $name)
        {
            $this->myName = $name;
            $this->subobj = new ItemClass ($val);
        }
    
        function getItem()
        {
            return ($this->subobj);
        }
    
    }
    
    class ItemClass  {
    
        private $value;
    
        function __construct($val)
        {
            $this->value = $val;
        }
    
    }
    

    如果您想为每个项目实现不同的功能,您需要覆盖您的库类。所以例如Project1ItemClass 扩展了库 ItemClass 类。这是一个例子:

    class Project1ItemClass extends ItemClass {
    
        function getDisplay () {
           return (/* some display */ $this->value);
        }
    
        function getDisplayAlone () {
           return (/* some display */"<DIV>" .  $this->value . "</DIV>");
        }
    
    }
    
    class Project1ContainerClass extends ContainerClass {
    
        //Override the constructor cause you want to create a project 1 specific ItemClass
        function __construct($val, $name)
        {
            $this->myName = $name;
            $this->subobj = new Project1ItemClass ($val);
        }
    
        function getDisplay () {
           return ($this->myName . " : " . $this->subobj->getDisplay());
        }
    }
    

    下面这个例子将打印:qwe : asd

    $Project1ContainerClass = new Project1ContainerClass("asd","qwe");
    echo $Project1ContainerClass->getDisplay();
    

    请注意,您应该覆盖项目特定ContainerClass 中的构造函数,因为您正在其中创建ItemClass 的新实例。如果您不覆盖构造函数,则您正在创建 ItemClass 的实例,而您的意图是 Project1ItemClass 的实例。

    【讨论】:

    • protected 有效,但对于 OP 的原始代码不是必需的。见test here。因此,除非明确声明 as private variables,否则无需修改库代码。 OP 还明确要求库源代码被修改。
    • 你说得对,但我的理解是他不想更改每个项目的库代码。他可以使他的变量受到保护,而不必再次更改代码。我的观点是类中的公共变量是一件坏事。所以这就是为什么我将它设置为受保护而不是默认的公共。
    • 确实如此。我不想为每个项目重写代码,假设我不需要知道它或控制它。最重要的是,可以有许多使用 ItemClass 的方法。如果交易是重写每个使用 Item 类的方法,那么为每个项目复制库并在其中添加添加的方法会更快、更安全。这就是我想要避免的。
    • 也许可以,但是如果您更改了一次库,那么您以后可以随时将其用于所有不同的项目。请注意,覆盖ItemClass 并不总是必要的,因为您可能不需要在某个项目中对其进行更改。此外,如果您覆盖 ItemClass,则不需要覆盖每个方法,而只需要覆盖与默认行为不同的方法。
    【解决方案2】:

    使用extends

    项目 1

    class ProjectItemClass extends ContainerClass {
    
        function getDisplay () {
            return (/* some display */ $this->value);
        }
    
        function getDisplayAlone () {
             return (/* some display */"<DIV>" .  $this->value . "</DIV>");
        }
    
    }
    
    class ProjectContainerClass extends ContainerClass {
    
        public function __construct($val, $name) {
            $this->myName = $name;
            $this->subobj = new ProjectItemClass ($val);
        }
    
        function getDisplay () {
            return ($myName . " : " . $this->subobj->getDisplay());
        }
    
    }
    

    项目 2

    class ProjectItemClass extends ContainerClass {
    
        function getDisplay () {
            return (/* some display */"Go to hell !");
        }
    
        function getDisplayAlone () {
            return (/* some display */"<DIV>What's up doc ?</DIV>");
        }
    
    }
    class ProjectContainerClass extends ContainerClass {
    
        public function __construct($val, $name) {
            $this->myName = $name;
            $this->subobj = new ProjectItemClass ($val);
        }
    
        function getDisplay () {
            if ($this->value == 5) return ($myName . " : " . $this->subobj->getDisplay());
            return ("No luck !");
        }
    
    }
    

    确保在原始类之后包含/需要这些新类,然后像这样使用它们:

    $obj = new ProjectContainerClass (10, "Me");
    $obj->getDisplay();
    $obj->getItem()->getDisplayAlone();
    

    注意覆盖__construct 以确保使用ProjectItemClass 而不是ItemClass。您还可以使用parent 调用来确保对扩展类构造的任何更改仍然可以使用(但$this-&gt;subobj 只会被调用两次。)

    public function __construct($val, $name) {
        parent::__construct($val, $name);
        $this->subobj = new ProjectItemClass($val);
    }
    

    【讨论】:

    • Smart,重写构造函数 ;)
    猜你喜欢
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 2023-03-13
    • 2020-07-01
    • 2011-04-14
    • 1970-01-01
    • 2012-03-21
    相关资源
    最近更新 更多