Php静态子类继承

时间:2012-10-29 15:46:33

标签: php oop

我最近开始以面向对象的方式在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()方法。

以下是我的尝试,这是我最终得到的混乱: - (

  • 对于Vocabulary_mongodb和Vocabulary_mysql,因为useVocab()不存在但是从词汇表继承," method_exists()"返回true和那个调用 导致无限循环。
  • 我看起来很奇怪,无论是在Vocabulary中显式调用子节点还是在子类中调用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
    }
}

我想知道如何设计词汇表类以保持词汇表:: ...像客户端和供应商中的调用一样,让词汇表知道哪个子类用于" Config&中配置的类型#34;类。

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

2 个答案:

答案 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用作全局存储的形式。保持对象自包含。