【问题标题】:Real World Examples of Advanced OOP Features for PHPPHP 高级 OOP 功能的真实示例
【发布时间】:2011-01-13 10:14:22
【问题描述】:

我正在努力提高我在 PHP 中的 OOP 知识,并且一直在研究抽象类和接口。

我学到了什么

  • 它们都是不能自己实例化但可以扩展的类(在接口的情况下实现)
  • 抽象类为扩展它们的其他类提供方法和属性。
  • 如果一个类使用抽象方法,那么该类本身也必须是抽象的。
  • 如果在抽象类中定义了抽象方法,则所有子类都必须定义该方法的详细信息。未定义为抽象的方法可以与普通方法一样使用。
  • 接口定义实现它的类必须具有的方法。接口中没有定义方法的功能,接口只是提供了一个必须包含在子类中的方法列表。
  • 接口未定义任何属性。
  • 类可以实现任意数量的接口,但它们必须为它们实现的每个接口定义一个方法

我认为这涵盖了基础知识。如果您认为我遗漏了什么,请随时补充。

我想知道的是,是否有这些类的实际实现示例,尤其是接口类。有谁知道任何使用它们的开源应用程序,我可以浏览它们以更好地理解它们并查看它们在何时何地被有效使用?我遇到过使用动物的书籍示例,这些示例未能证明这些课程的重要性。

【问题讨论】:

    标签: php oop


    【解决方案1】:

    final关键字防止该类被其他类扩展,例如:

    class Parent
    {
    }
    
    class Mother extends Parent
    {
    }
    
    final class Brother extends Mother /* - This class cannot be extended - */
    {
    }
    
    class Pet extends Brother
    {
    }
    

    Pet 类将抛出错误声明:Fatal error: Class Pet may not inherit from final class (Brother)

    这也适用于方法,因此如果您不想让方法被继承,从而导致子类具有相同的方法作为覆盖。

    http://php.net/manual/en/language.oop5.final.php

    你曾经说过你想要一些真实世界的例子来说明接口可以用于什么,以及数据库抽象层

    您有 1 个基类,它提供了迭代数据库数据的基本方法,但这将使用数据库类型的子类,例如 MySqlMsSql 等,每种数据库类型都有自己的类,但基类要确保它具有这些方法,它们都将实现相同的接口。

    例子

    interface IDatabaseLayer
    {
        public function connect();
        public function query();
        public function sanitize();
        //...
    }
    

    所以基类知道MySql和MsSql有上述方法,从而减少错误,更有条理。

    在将对象传递给类时,您希望确保该对象属于某种类型,PHP5 允许您定义应将哪种类型的对象作为参数传递给方法。

    假设你有 3 个课程

    • DatabaseCredentials
    • DatabaseConnection
    • DatabaseQuery

    您可以在 DatabaseConnection 的构造中明确定义您需要一个 DatabaseCredentials 类,如下所示:

    class DatabaseConnection implements Connectable
    {
        public function __construct(DatabaseCredentials $ConnectionDetails)
        {
            $this->Connect($ConnectionDetails->BuildDSN());
        }
    }
    

    真正入门的好方法是阅读此处:


    您可能希望了解的 PHP5 的另一个特性是名称空间,这将使您的代码保持井井有条,拥有多个同名对象,使自动加载更有效

    小例子:

    namespace Database\MySql
    {
        class Database{}
    }
    
    namespace Database\MsSql
    {
        class Database{}
    }
    

    你可以像这样使用:

    use Database;
    $Database = new MySql\Database();
    

    【讨论】:

    • 我读到命名空间字符是\。我有点迷路了,是/还是\?
    【解决方案2】:

    PHP 自带几个默认预定义的接口:http://www.php.net/manual/en/reserved.interfaces.php

    PHP 还包含标准 PHP 库 (SPL),它定义了更多:

    Zend Framework 也是使用这些概念的一个很好的例子。 http://framework.zend.com/

    【讨论】:

    【解决方案3】:

    Command Pattern 这不是一个真实世界的示例,但您通常会遇到接口和抽象类的一种设计模式。示例代码见链接。

    一般来说,“针对接口编程”被认为是良好的 OO 实践,因为它解耦了具体的实现并让您更轻松地为其他实现更改它们,例如而不是要求特定的课程

    public function fn(ConcreteClass $obj)
    {
        $obj->doSomething()
    }
    

    你只是要求它提供了一组特定的方法

    public function fn(MyInterface $obj)
    {
        $obj->doSomething()
    }
    

    接口还有助于区分大型继承结构。因为 PHP 只支持单一继承,你会经常看到这样的层次结构:

    BaseClass -> Logger -> Auth -> User
    

    其中每一个都包含这些类中使用的特定方面。有了界面,你就可以做

    User implements Loggable, Authenticable
    

    然后通过策略模式或组合/聚合包含特定代码,这最终更易于维护。

    有关 PHP 中预定义接口的列表,请参阅我的回答:

    【讨论】:

      【解决方案4】:

      您可以在 dzone 中关注 Giorgio Sironi 的 "PHP patterns" series 或直接在 his blog 中关注,如果您对模式和 OOP 感兴趣,真的很有趣。

      如果您需要一本好的 PHP 书籍,也可以查看 stackoverflow 中的 Best PHP programming book

      【讨论】:

        【解决方案5】:

        我们可以说接口是纯粹的 100% 抽象类,但抽象不是。因为很多时候我们在抽象类中定义函数。但是在接口类中,我们总是声明函数。

        【讨论】:

          猜你喜欢
          • 2010-11-23
          • 1970-01-01
          • 2022-08-10
          • 2012-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-17
          相关资源
          最近更新 更多