1

我最近开始以面向对象的方式在 php5 中进行开发,但我遇到了一些问题。我非常感谢您的帮助/建议。

忍受我,因为它最终一团糟:-(

这是我的场景(希望我能详细说明):我有两个动态类,Client 和 Supplier,它们使用名为 Vocabulary 的静态类的方法。Vocabulary 是一个从源中提取词汇术语的类,该源可以是:纯文本文件、mongodb 数据库或 mysql 数据库。配置文件中的一个条目决定了应用程序将使用上述三种来源中的哪一种。

class Client {
    public function foo() {
        ...
        Vocabulary::getTerm();
        ...
    }
    ...
}

class Supplier {
    public function bar() {
        ...
        Vocabulary::getTerm();
        ...
    }
    ...
}

class Vocabulary {
    public static function useVocab($vocab) {
        $_SESSION['vocab'] = $vocab;
    }
    public static function getTerm($termKey) {...}
    ...
}

我计划为我想要支持的每种类型创建 Vocabulary 子类,例如:Vocabulary_file、Vocabulary_mongodb 和 Vocabulary_mysql。Vocabulary_file 将覆盖其父 useVocab(),因为它需要执行额外的操作来设置 $_SESSION 变量,但 Vocabulary_mongodb 和 Vocabulary_mysql 不需要覆盖它们的 useVocab() 父方法(它们只需要设置 $_SESSION 变量)。所有三个词汇“子”类都将覆盖 getTerm() 方法。

以下是我尝试过的,这是我最终得到的一团糟:-(

  • 对于 Vocabulary_mongodb 和 Vocabulary_mysql,由于 useVocab() 不存在而是从 Vocabulary 继承,“method_exists()”返回 true,并且该调用导致无限循环。
  • 我在 Vocabulary 中显式调用 child 和在 child 类中调用 parent:: 看起来很奇怪。

喝了很多杯咖啡后,我已经筋疲力尽了,我的大脑也受损了。

// Class Vocabulary modified to make it call the desired "child" class too
class Vocabulary {
    // This would execute "child" class method
    private static function _callChild($method, $args) {
        $child_class = 'Vocabulary_' . Config::$vocab['type']; // Config::$vocab['type']     can be: file, mongodb or mysql
        if (method_exists($child_class, $method)) {
            return call_user_func_array($child_class . '::' . $method, $args);
        } else {
            return false;
        }
    }
    public static function useVocab($vocab) {
        $_SESSION['vocab'] = $vocab;
        self::_callChild(__FUNCTION__, compact('vocab'));
    }
    public static function getTerm($termKey) {
        $termKey = strtolower($termKey);
        self::_callChild(__FUNCTION__, compact('termKey'));
    }
    ...
}

class Vocabulary_file extends Vocabulary {
    public static function useVocab($vocab) {
        parent::useVocab($vocab);
        // some specific stuff here
    }
    public static function getTerm($termKey) {
        parent::getTerm($termKey);
        // some specific stuff here
    }
}

class Vocabulary_mongodb extends Vocabulary {
    public static function getTerm($termKey) {
        parent::getTerm($termKey);
        // some specific stuff here
    }
}

class Vocabulary_mysql extends Vocabulary {
    public static function getTerm($termKey) {
            parent::getTerm($termKey);
        // some specific stuff here
    }
}

我想知道如何设计 Vocabulary 类以保持 Vocabulary::... 像 Client 和 Supplier 中的调用,并让 Vocabulary 知道哪个子类用于“Config”类中配置的类型。

任何建议将不胜感激。干杯

4

2 回答 2

0

该关键字self无法处理“后期静态绑定”。基本上,在父类中,self当它在它自己的静态函数中时认为它是父类(因为由于self遗留原因仍在编译时评估)。

您需要在父类中使用static而不是self(假设您有 php 5.3 或更高版本)。

顺便说一句:parent关键字的功能正如您所期望的那样,parent无论如何必须在编译时知道。

这是一个例子:

public static function getTerm($termKey) {
    $termKey = strtolower($termKey);
    static::_callChild(__FUNCTION__, compact('termKey'));
}

如果您使用的是 php 5.2 及更早版本,则必须尝试破解,例如要求所有子类具有返回其类名的静态函数。我希望您使用的是 php 5.3 或更高版本...

于 2012-10-29T15:52:47.133 回答
0

如果你使用所有static方法,你可能根本不使用OOP,它基本上只是全局函数调用。如果您希望使用多态性进行继承,您几乎需要实例化您的类。多态性来自于实例化对象可以是任何东西的事实,但是您在它们上调用相同的方法。例如:

abstract class Vocabulary {

    abstract public function getTerm($termKey);

}

class Vocabulary_File extends Vocabulary {

    public function getTerm($termKey) {
        // get from file
    }

}

class Vocabulary_MySQL extends Vocabulary {

    public function getTerm($termKey) {
        // get from database
    }

}

你可以像这样使用这个多态:

if (mt_rand(0, 1)) {
    $vocab = new Vocabulary_File;
} else {
    $vocab = new Vocabulary_MySQL;
}

// This call is polymorphic.
//  What exactly it does depends on which class was instantiated.
$vocab->getTerm('foo');

这就是多态性真正有用的地方。接口( getTerm($termKey)) 是定义好的,类之间是不变的,但具体的实现会发生变化。如果您的代码是对 的硬编码调用Vocabulary::getTerm(),那不是多态性。对于您的结构,您还违反了一个重要的 OO 设计规则:父级不知道其子级,也不与子级交互。子代覆盖父代的功能,而不是相反。

您也不应该将$_SESSION用作全局存储的一种形式。保持对象自包含。

于 2012-10-29T16:01:36.717 回答