构造函数导致无限循环

时间:2018-07-16 20:37:32

标签: php oop

我正在尝试完成this PHP challenge,并且我目前拥有以下代码:

<?php

/*
Challenge 2: Implement AnswerInterface and get Question to echo "4".
*/  
class Question
{
    public function __construct(AnswerInterface $answer)
    { 
        echo "What is 2 + 2?\n";
        $answer = $answer->get()->the()->answer();
        if ($answer instanceof AnswerInterface) {
            echo $answer . PHP_EOL;
        }
    }   
}   

interface AnswerInterface
{   
    public function get();
    public function the();
    public function answer();
}   

class Answer implements AnswerInterface
{   
    public function get()
    {   
        return new Answer();
    }

    public function the()
    {
        return new Answer();
    }

    public function answer()
    {
        return new Answer();
    }

    public function __toString()
    {
        return '4';
    }
}

$answer = new Answer;
$question = new Question($answer);

当我运行这样的代码时,它给了我错误:

Fatal error: Allowed memory size of 134217728 bytes exhausted

我可以通过在代码中插入以下内容来纠正错误:

public function __construct() {}

我不完全了解它是如何工作的...我想了解这里发生了什么。非常感谢您提供任何帮助,以解释其工作原理。

2 个答案:

答案 0 :(得分:6)

在PHP拥有__construct之前,您将通过命名与该类同名的方法来创建构造函数。它仍然受支持,但是在PHP 7中已弃用。这意味着,如果您的Answer类没有现代构造函数(__construct),则answer方法将被称为构造函数。由于它返回new Answer,因此将在新对象上一次又一次地调用构造函数。您有无限的递归,一旦内存耗尽,就会引发错误。

我只能猜测此练习的原因是什么。但是您也可以只在$thisgetthe中返回answer。如果您希望您的类支持“链接”,那通常就是您要做的。当然,在现实世界中,这些方法还会做其他事情。

答案 1 :(得分:2)

基本上您有正确的思维方式,但是问题是您不需要在所有方法中都创建新实例,您需要的只是返回对象的当前实例,因为您已经创建了对象Answer并将其传递给问题对象,因此正确的代码应如下所示:

class Answer implements AnswerInterface
{

public function get()
{
    return $this;
}

public function the()
{
    return $this;
}

public function answer()
{
    return $this;
}

public function __toString()
    {
        return "4";
    }
}

您还可能想在PHP: The Basics

上了解有关$ this关键字的信息

如果您在PHP 5.3.3之后不使用命名空间,则方法answer()也将被视为类Answer的构造函数方法(无论是小写还是大写)(或者如果您有,则将其视为构造函数) PHP 5.3.0-5.3.2)。因此,在您的情况下,尝试在已实现的方法中调用新的Answer()时也会遇到无限循环。