【问题标题】:php class to inherit only one methodphp类只继承一种方法
【发布时间】:2011-12-06 09:17:54
【问题描述】:

我有这些课程:

class User{
    private $user_ID;
    private $first_name;
    private $surname;
    ...

    private $website;
    private $company;

    function __construct($array){
        $this->user_ID            = $array["userId"];
        $this->first_name         = $array["first"];
        $this->surname            = $array["last"];
        $this->telephone          = $array["tele"];
        ...
    }
    public function addWebsite($array){
        $this->website = $array;
    }
    public function addCompany($array){
        $this->company = $array;
    }
    public function getData(){
        $array = array();
        foreach($this as $var => $value) {
            $array[$var] = $value;
        }
        return $array;
    }
}

class Website{
    private $webId;
    private $url;
    private $description;
    ...

    function __contruct($array){
        $this->webId           = $array["webId"];
        $this->url             = $array["url"];
        $this->description     = $array["desc"];
        ...
    }
}

User 中的 getData() 方法与 Website 类完全相同。

那么我怎样才能让网站类来实现这个方法呢?但只有 getData() 方法

【问题讨论】:

    标签: php oop class inheritance


    【解决方案1】:

    虽然继承形成behaves-as relationship,但继承不是这种情况。您的 WebsiteUser 没有任何关系,因此它们之间不应该有任何关系。

    拥有base classes 就像这里其他地方建议的那样,将很快导致单体架构和god objects。这些反过来导致less maintainability, high coupling, fragile code and hampers reuse。同样,将所有内容公开或诉诸类似意味着击败信息隐藏并扩大公共 API 会导致类似问题,您将希望避免它们。

    您正在寻找的是Traits,但这些仅从 PHP 5.4 开始受支持。最简单的方法实际上只是在两个类中复制该方法。请记住,您通常希望避免代码重复,但在这种情况下,与其他建议的替代方案相比,它的危害较小。

    一个可行的替代方法是使用自省服务,该服务使用反射将数据从对象提取到数组中。虽然一般来说,you should put methods on the objects having the data the methods operate on.

    【讨论】:

      【解决方案2】:

      如果您使用的是 php5.4,您可以使用特征而不是类。它解决了您需要在两个不同的类中实现一种方法的情况。

      【讨论】:

      • 如果您当前在生产环境中使用 php5.4,那么您就生活在边缘。这是一个 RC,就像它在 php.net 上所说的那样:“这是一个发布候选 - 不要在生产中使用它!”
      【解决方案3】:

      要使其类型保存,您可以定义一个接口,例如具有 getData 方法的“arraySerializable”。您可以稍后在 TypeHints 中使用此接口而不是类。

      但这仍然没有为您提供功能。我想一个通用的基类不是你想要的东西。因此,如果您不能使用特征,则必须复制代码。这可能是某些行重复代码正常的罕见情况之一。

      【讨论】:

        【解决方案4】:

        创建另一个仅具有 getData 方法的类,并使现有的两个类都扩展该新类。

        【讨论】:

        • -1 因为有一个基类会打乱继承链,阻碍重用,并且会很快导致上帝对象和单体架构。
        • +1 因为它不会按照你说的去做。这是唯一可行且可维护的解决方案。如果它确实是 OP 正在谈论的一段相同的代码,那么唯一值得反对的答案是你的答案,@Gordon,因为你(是的,除其他外)建议复制和粘贴。
        【解决方案5】:

        如果您没有 Traits,则可以使用较旧的 Mixins 实现。

        你可能知道:

        <?php
        
        class A {
            public function B() {
                var_dump($this->data);
            }
        }
        class X {
            protected $data;
            public function Y() {
                A::B()
            }
        }
        
        $x = new X;
        $x->Y(); // will execute the code for A::B 
                 // but will assume the object context
                 // of $x (of class X) and will have
                 // access to $this->data
                 // ! this is not a static call
        

        使用此原理,您可以创建一个静态数组,其中包含类名和/或方法名,您可以通过魔术方法 __get “混合”或“使用”(如特征)。 ?>

        【讨论】:

          【解决方案6】:

          与其他回答者相反,我认为我应该评论您的设计。您想创建一个公开任何对象的所有私有属性的方法。在大多数情况下,对象不仅仅是一个属性包,那么在什么情况下您需要了解所有属性?你为什么还要将它们标记为私有?

          要解决真正的问题,如果你想控制传入和传出数据,你应该看看公共属性,或者带有 getter 和 setter 的私有属性。

          但是,如果您认为您需要给定对象的所有属性(并且愿意接受诸如复制粘贴编程、特征和诸如此类的“黑客”),为什么不简单地将它们标记为公共并调用 get_object_vars()

          【讨论】:

          • 没有 dv 但我认为它是某种形式的数据映射,它被用于此。在这种情况下,可以使用以太结构/getData 接口或公共属性或反射。不过,在我的书中,没有公共属性是一个有效的选择:)
          • @edorian 如果它是某种数据访问层或模板层,从一种包含 GetData 方法的 TemplateObject 或 DAOObject 派生应该是要走的路。如果没有,我真的很想看看 OP 想要完成什么。通过单一方法返回所有对象的所有私有属性在我看来就像 OP 没有得到属性(或对象......)的用途。
          • -1 建议当 OP 真的只想要数组中的数据时添加 getter/setter。您建议扩大公共 API,而不是保持其小而专注。除非该对象是一个值对象,否则您应该使用Getters and Setters avoid littering 它。
          • @CodeCaster 从 DAOObject 派生将是(或至少接近于)“活动记录”,并且与之相关的问题非常多(请参阅 RoR 或 Cake 的问题)和在大多数情况下被“数据映射器”超越。但它可能是有效的选择,而不是 OP 所采用的选择 :)
          • @Gordon 是的,对 OP 问题的唯一有效答案是“使用特征”或“将其复制粘贴到所有地方”,你是对的。不,等等,“使用符合 GetData 方法目的的基类”可能是一个非常明智的解决方案,以及使用公共属性或 getter 和 setter,取决于 OP 想要完成的任务 .但它不止一次让我震惊。 OP 要求一些不太常见的东西(他可能很可能不需要,但未能解释他真正想要的东西),OP 得到了他的答案,并在遗忘中生活。好吧,祝你好运。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-14
          • 2019-11-27
          • 2011-03-03
          • 2020-08-27
          • 1970-01-01
          • 2020-10-12
          相关资源
          最近更新 更多