php - 构造父类时设置对象的子类(动态子类)

标签 php oop

编辑:为了消除一些困惑,我实际上并没有使用 MaleFemale。一个更好的例子是父类 Animal 和子类 CatDog
我对 OOP 有点陌生,但到目前为止我已经很好地掌握了它。然而,有一件事我完全可以找到一种方法来做。
首先,我创建一个基于用户的新对象。用户可以是(对于本例)男性或女性,但如果不检查数据库,我无法检查他们是否是男性或女性。然后,我需要使用其性别的子类创建一个新的用户对象。
例如,这是我当前的(困惑的)代码:

$user = new Person();
$userType = $user->GetUserType($userid);
if ($userType == 'Male') {
    $user = new Male($userid);
} else {
    $user = new Female($userid);
}

如果我想创建一个新对象,我每次都必须这样做,这是我不想做的事情。
这里还有一些代码可以帮助我们正确理解这一点:

class Person {
function GetUserType($userid) {
        $db = mysqlConnect();
        $stmt = $db->stmt_init();
        // Get the players information
        $stmt->prepare("SELECT user_type FROM user_information WHERE user_id = ?");
        $stmt->bind_param('i', $userid);
        $stmt->execute();
        $stmt->bind_result($userType);
        $stmt->fetch();
        $stmt->close();
        $db->close();
        return $userType;
    }
}
class Male extends Person {
    // Male based things here
}
class Female extends Person {
    // Female based things here
}

因此,在 Person 类的 __construct 中,我希望它检查用户的性别并设置适当的子类。

最佳答案

So, in the __construct of the Person class, I'd like it to check for the users sex and set the appropriate sub-class.

就像在其他地方已经说过的那样, Actor 不会回来,所以你不能这样做。而且参与者无论如何都不应该查询数据库,因为that would be doing work 。如果您不能/不想立即通过 DataMapper 创建正确的子类型或Repository ,您可以使用 State Pattern :

Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

这是 Behavioral Patterns 之一来自Gang Of Four book 。显然,这里的关键词是行为。状态模式并不是关于不同的子类型(猫、狗)本身,而是关于它们的行为差异。因此我对你的问题发表评论。

示例:

interface GenderBehavior
{
    public function someBehavior();
    // can add more methods here
}

class FemalePersonBehavior implements GenderBehavior
{
    public function someBehavior()
    {
        // female specific behavior
    }
}

class MalePersonBehavior implements GenderBehavior
{
    public function someBehavior()
    {
        // male specific behavior
    }
}

class UnknownGenderBehavior implements GenderBehavior
{
    public function someBehavior()
    {
        // either implement a neutral behavior or
        throw new LogicException('Unknown Gender set');
    }
}

要创建这些实例,您需要添加 Factory

class GenderBehaviorFactory
{
    public static function create($sex = null)
    {
        switch ($sex) {
           case 'male':
               return new MalePersonBehavior;
           case 'female':
               return new FemalePersonBehavior;
           default:
               return UnknownGenderBehavior;
        }
    }
}

然后,将 GenderBehavior 接口(interface)添加到 Person 类,并将对接口(interface)方法的所有访问传送到Behavior 实例:

class Person implements GenderBehavior
{
    private $behavior;

    public function __construct()
    {
        $this->behavior = GenderBehaviorFactory::create();
    }

    public function changeGender($sex)
    {
        $this->behavior = GenderBehaviorFactory::create($sex);
    }

    public function someBehavior()
    {
        $this->behavior->someBehavior();
    }
}

现在,当您第一次创建 Person 时,它将使用 UnknownGenderBehavior 进行实例化,如果您尝试调用 someBehavior,它将引发异常。当您以男性或女性作为参数调用 changeGender 时,将创建适当的 GenderBehavior 并将其设置为 Person。然后你可以调用someBehavior

关于php - 构造父类时设置对象的子类(动态子类),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10565843/

相关文章:

algorithm - 搜索算法 : Parsing and processing a request OOP style

java - 解析进程 : keeping classes/instances separate or having them chained?

oop - 大型嵌套 switch 语句的设计模式

python - 每次调用时创建 python 类的新副本

php - 服务器 :run stuck in other project

php - simpleSAMLphp:无法找到当前绑定(bind)

php - 是否可以在 mysql 中选择 SET 的所有单个字符串?

php - Elasticsearch-PHP批量

PHP PDO 准备和执行 MySQL UPDATE 语句不起作用 - 难倒了!

c# - 这段代码应该是基类而不是接口(interface)吗?