【问题标题】:In PHP, is it possible to return a class's constructor function?在 PHP 中,是否可以返回类的构造函数?
【发布时间】:2012-01-17 14:05:18
【问题描述】:

我在 PHP 中遇到了一种情况,我需要在不知道类是什么的情况下访问类的构造函数。我可能从错误的设计角度来处理这个问题,所以情况就是这样——我在 Drupal 工作,围绕他们的无类数据处理编写一个轻微的 OO 层,以允许一些非 Drupal 开发人员加入我的项目。

在 Drupal 中,所有内容都被视为一个节点。所以,我做了一个抽象类——Node。任何内容都必须具有特定的内容类型。使用 OO,这很容易——我创建了一个扩展 Node 的 Person 类,或者一个扩展 Node 的 Event 类等。现在是棘手的部分——我的项目的一部分允许这些节点“包含”在其他节点中。也就是说,如果节点 A 包括节点 B,那么无论何时显示 A,都会显示来自 B 的数据。这意味着每当实例化节点 A 时,它也需要实例化节点 B。但是...Node 是一个抽象类。所以,我不能实例化一个原始节点。我必须实例化它的一个实现类。所以,据我所知,我要么需要编写一个抽象的静态函数,所有扩展类都必须实现它返回构造函数......要么,我需要以某种方式使用反射来确定类型,并以某种方式调用合适的类构造函数?

不考虑 Drupal,从 PHP/OO 编程的角度来看,处理此问题的最合适方法是什么?

这是我的代码:

<?php

abstract class Node {

    public $title, $short_summary, $full_summary, $body, $uri, $machine_type_name, $included_content;

    public function __construct($node) {

        ##
        ## Set simple values
        $this->title = $node->title;
        $this->body = $node->body['und'][0]['safe_value'];

        ##
        ## Set clean uri if aliased
        if (drupal_lookup_path('alias', 'node/'.$node->nid)) {
            $this->uri = '/'.drupal_lookup_path('alias', 'node/'.$node->nid);
        } else {
            $this->uri = '/node/'.$node->nid;
        }

        ##
        ## Set short summary if exists, else short form of body text
        if(strlen($node->body['und'][0]['safe_summary'])) {
            $this->short_summary = $node->body['und'][0]['safe_summary'];
        } else {
            $this->short_summary = text_summary($node->body['und'][0]['safe_value'], NULL, 100);
        }

        ##
        ## Set full summary to concatenation of body
        $this->full_summary = text_summary($node->body['und'][0]['safe_value'], NULL, 600);

        ##
        ## Add included content if module is enabled
        if (module_exists('content_inclusion')) {
            // is this possible? Is there a better design pattern available?
            $this->included_content = Node::get_constructor(node_load($node->content_inclusion['und'][0]['value']));
        }

    }

    public static abstract function get_all_published();
    public static abstract function get_by_nid($nid);
    public static abstract function get_constructor();
}

?>

【问题讨论】:

  • 瑞恩,认识static。我相信你们会成为好朋友的。
  • 虽然感谢您的帮助,但我显然对上面的代码中的 static 关键字有所了解。除非我遗漏了什么,否则我看不出这如何解决我的问题。
  • 但是你遇到过它的同卵双胞胎static,用于后期静态绑定吗? (docs)

标签: php oop object inheritance


【解决方案1】:

你的意思是:?

class MySubClass extends Node
{
    public static function get_constructor()
    {
        return new self();
    }
}

// ...

$object = MySubClass::get_constructor();

或者,如果你有 PHP 5.3,你可以使用 late static binding,你可以使用 return new static();$class = get_called_class(); return new $class();。等等。

完整示例:

abstract class Node 
{
    public $test;

    public function __construct()
    {
        $this->test = 'Node';
    }

    public static function get_constructor()
    {
        return new static();
    }
}

class MySubClass extends Node
{
    public function __construct()
    {
        $this->test = __CLASS__ . PHP_EOL;
    }
}

// ...

$object = MySubClass::get_constructor();
echo $object->test; // echoes "MySubClass"

【讨论】:

  • Node 是一个抽象类,所以它不能被实例化。我需要一个未知的类实现 Node 来实例化。
  • 它应该仍然可以工作。只要你用你的子类名来调用它。 (例如MySubClass::get_constructor();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-25
相关资源
最近更新 更多