我最近开始以面向对象的方式在php5中开发,而我却陷入困境。我非常感谢您的帮助/建议。
因为它最终陷入了混乱,所以忍受我: - (
这是我的场景(希望我能清楚地详细阐述):我有两个动态类,Client和Supplier,它们使用一个名为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_file,Vocabulary_mongodb和Vocabulary_mysql。 Vocabulary_file将覆盖其父useVocab(),因为它需要通过设置$ _SESSION变量来执行其他操作,但是 Vocabulary_mongodb和Vocabulary_mysql不需要覆盖它们的useVocab()父方法(它们只需要$ _SESSION变量集)。 所有三个词汇"孩子"类将覆盖getTerm()方法。
以下是我的尝试,这是我最终得到的混乱: - (
喝了很多杯咖啡后,我已经筋疲力尽了,我的大脑也被损坏了。
// 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
}
}
我想知道如何设计词汇表类以保持词汇表:: ...像客户端和供应商中的调用一样,让词汇表知道哪个子类用于" Config&中配置的类型#34;类。
任何建议都将不胜感激。 干杯
答案 0 :(得分:0)
关键字self
无法处理'后期静态绑定'。基本上,在父类中,self
认为它是父类,当它在它自己的静态函数中时(因为self
仍然在编译时由于遗留原因而被评估)。
您需要在父类中使用static
而不是self
(假设您拥有php 5.3或更高版本)。
BTW:parent
关键字的功能与您期望的一样,因为无论如何必须在编译时知道parent
。
以下是一个例子:
public static function getTerm($termKey) {
$termKey = strtolower($termKey);
static::_callChild(__FUNCTION__, compact('termKey'));
}
如果您使用的是PHP 5.2及更早版本,则必须尝试黑客攻击,例如要求所有子类具有返回其类名的静态函数。我希望你在php 5.3或更高版本上...
答案 1 :(得分:0)
如果你正在使用所有static
方法,你可能根本不使用OOP,它基本上只是全局函数调用。如果您希望继承多态,那么您几乎需要实例化您的类。然后,多态性来自这样的事实:实例化的对象可以是任何东西,但是你在它们上面调用相同的方法。 E.g:
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
用作全局存储的形式。保持对象自包含。