PHP中的继承 - 创建子类实例并调用父类方法

3

我有类似这样的东西:

class MyParent {
    protected static $object;
    protected static $db_fields;

    public function delete() {
           // delete stuff
    }


    public static function find_by_id($id = 0) {
        global $database;
        $result_array = self::find_by_sql("SELECT * FROM " . static::$table_name . " WHERE id=" . $database -> escape_value($id) . " LIMIT 1");
        return !empty($result_array) ? array_shift($result_array) : false;
    }

     public static function find_by_sql($sql = "") {
        global $database;

        // Do Query
        $result_set = $database -> query($sql);

        // Get Results
        $object_array = array();
        while ($row = $database -> fetch_array($result_set)) {
            $object_array[] = self::instantiate($row);
        }

        return $object_array;
    }

   private static function instantiate($record) {
        $object = self::$object;
        foreach ($record as $attribute => $value) {
            if (self::has_attribute($attribute)) {
                $object -> $attribute = $value;
            }
        }
        return $object;
    }


}


class TheChild extends MyParent {

    protected static $db_fields = array('id', 'name');
    protected static $table_name = "my_table";

    function __construct() {
        self::$object = new TheChild;
    }

}

$child= TheChild::find_by_id($_GET['id']);
$child->delete();

我理解到的是:在上面的最后一行代码中,出现了“调用未定义的方法stdClass::delete()”的错误提示。这是继承方面缺少的步骤导致的吗?

stdClass 不是你的类 Child。你确定这是展示错误的确切代码吗? - SirDarius
不要展示你所期望的代码,而是展示你实际拥有的代码。如果必须缩减,请确保不让我们猜测 =) - Mike 'Pomax' Kamermans
抱歉,我试图展示一般原则。我真的想知道上面的方法是否可行;如果正确,那么问题就更深入了。我会看看能否添加更多内容。 - TheLettuceMaster
你关于创建一个SSCCE的想法已经非常接近了,唯一需要注意的是确保它能够重现错误。 - Paul
我已经添加了更精确的代码。 - TheLettuceMaster
由于您的代码中未出现find_by_sql,因此我们无法确定find_by_id返回什么。 - SirDarius
2个回答

2

您从未实例化TheChild类,这应该由以下方式完成:

$var = new TheChild();

除了在TheChild构造函数本身中,静态变量$object永远不会受到影响(至少在您的示例中如此)。因此,将字段分配给它(行$object -> $attribute = $value;)会导致stdClass对象的创建,如此交互式PHP shell会话所示:

php > class Z { public static $object; }
php > Z::$object->toto = 5;
PHP Warning:  Creating default object from empty value in php shell code on line 1
php > var_dump(Z::$object);
object(stdClass)#1 (1) {
  ["toto"]=>
  int(5)
}

这个对象没有delete方法。

正如之前所说,实际上创建一个TheChild实例将导致无限递归。

你想做的可能是这样的:

class TheChild extends MyParent {

    protected static $db_fields = array('id', 'name');
    protected static $table_name = "my_table";

    function __construct() {
        self::$object = $this;
    }

}

1
编辑:您更新的代码展示了一个完全不同的示例:
class MyParent {
    protected static $object;

    public function delete() {
           // delete stuff
    }
}


class TheChild extends MyParent {

    function __construct() {
        self::$object = new TheChild;
    }


}

$child = new TheChild;
$child->delete();

在“子类”的构造函数中调用自身的构造函数将导致无限循环。
 function __construct() {
        self::$object = new TheChild; // will trigger __construct on the child, which in turn will create a new child, and so on.
    }

也许 - 我不知道你想要实现什么 - 你正在寻找:
 function __construct() {
        self::$object = new MyParent;
    }

请注意,:: 符号不仅仅是 -> 的另一种版本 - 它们完全不同。一个是静态访问,而另一个是对实际对象实例的访问!

似乎“Parent”只是一个示例名称,因为自您发布此答案以来,问题已被编辑。 - SirDarius
抱歉,是的,那只是一个例子;我已经在上面重命名了它。 - TheLettuceMaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接