PHP类/OOP:何时;参考“;类中的类vs扩展类


PHP Class / OOP : When to "reference" a class within a class vs extend a class?

什么时候最理想:

class USER {
    // stuff about user
}
class PROFILE extends USER {
    // stuff about user's profile
}

什么时候最理想:

class USER {
    $id;
    $profile;
    function __construct($id) {
        $this->id = $id;
        $this->profile = new PROFILE($id);
        // set profile variables
    }
}
class PROFILE {
    $id;
    // other variables pertaining to profile
    function __construct($id) {
        $this->id = $id;
    }
}

我觉得第二个例子更舒服?有什么特别的注意事项我应该知道吗?

我应该把一个看作不是互斥的子集,把另一个看作孩子吗?

这是封装和继承的经典问题。

使用封装:

  • 当您想提供基类的一些功能,但又想隐藏其中的一些功能时
  • 当您希望扩展/修改基类的功能,但不需要它与类型兼容时

使用继承:

  • 当您需要派生类与基类的类型兼容时。换句话说,如果客户端代码需要引用具有Base引用的Derived实例

在您的示例中,PROFILE从USER派生是没有意义的。用户具有配置文件,但配置文件不是用户。对于本例,USER类包含一个PROFILE字段是有意义的。

我认为真正的方法是:

class User {
    private $id,
            $profile;
    public function __construct($id, Profile $profile) {
        $this->id = $id;
        $this->profile = $profile;
    }
}
class Profile { ... }
new User(42, new Profile(...));

除非有明确的层次结构(Admin extends User),否则您不希望扩展类
您也不应该像在User构造函数中那样耦合类,而应该使用如上所示的依赖注入。

通常,除非您可以说PROFILE只是USER的一种特殊类型,并且在所有情况下都可以像对待USER一样对待,否则您不希望使用继承来为关系建模。USER可能具有PROFILE,或者PROFILE可能与特定USER关联,但两者是不同的实体,因此两者都不应继承。

通常父类更像是要扩展的泛型类,很少单独使用。因此,继承更像是它应该有的样子:扩展一个泛型类。

我不会再使用动物的比喻了,而是类似于:

class USER {} // generic class
class ADMIN extends USER {} // specific class
class MOD extends USER {} // specific class

有一个逻辑,因为我们扩展了一个通用的USER类,为每种类型的用户指定一个类。

对于任何其他不分层的东西,我都会使用封装。