即使参数正确传递,参数错误也很少

时间:2018-09-18 11:20:17

标签: php

运行此命令时,它会抱怨

  

函数Base :: __ construct()的参数太少,在第18行的[FileName] .php中传递了0,并且恰好期望了1

class Base {
    protected $var;
    public function __construct($var){
        $this->var = $var;
    }
}

class ChildA extends Base {
    public function handle(){
        echo $this->var;
    }
}

$base = new Base(10);

(new ChildA())->handle();

但是如您所见,我已通过: $base = new Base(10);

编辑:如答案和评论中所述,问题不在此处:

$base = new Base(10);

...但是在这里:

(new ChildA())->handle();

我在做什么错?另外,我要尝试实现的是,有许多ChildX类需要扩展Base,并且所有这些子类都必须具有$var属性。因此,我不想在每个子类中复制$ var,而是希望通过将其放在父类中来减少键入的工作量。但是显然,我的计划没有实现。

4 个答案:

答案 0 :(得分:2)

您的问题实际上是这一行:

(new ChildA())->handle();

执行此操作:

$child = new ChildA(10);
$child->handle();

您不需要单独实例化基类。

另一件事。当父类和子类都具有构造函数时,可以将parent::__construct($whatever);放在子类的构造函数中以同时运行父代码。

答案 1 :(得分:2)

这是类实例化的简单概念,我认为您错了。

完成时

$base = new Base(10);

您仅在创建Base类的实例。

但是,以下语句调用Child类的另一个实例。请注意,基本变量和此子实例是两个不同的实体,因此它们的行为不会互相影响。

(new ChildA())->handle();

因此,当前基本变量的值将为10,但是handle()函数调用无法实例化,因为它需要一个要提供给Base类新实例的参数。

您将需要实例化子类,因此将首先调用继承的类的构造函数并设置您的变量。这样,您的handle()函数就可以成功返回正确的值。

$child = new Child(10); $child->handle(); //returns 10

答案 2 :(得分:1)

扩展类时,默认情况下,该类上的所有方法都存在于子类上,包括诸如__construct之类的“魔术”方法。

因此,当您编写此代码时:

class Base {
    protected $var;
    public function __construct($var){
        $this->var = $var;
    }
}

class ChildA extends Base {
    public function handle(){
        echo $this->var;
    }
}

您的子类实际上看起来像这样:

class ChildA extends Base {
    // Inherited property from Base class
    protected $var;

    // Inherited method from Base class
    public function __construct($var){
        $this->var = $var;
    }

    // New method in this class
    public function handle(){
        echo $this->var;
    }
}

这是一个略微的简化,我们将在下面看到,但是它解释了您的示例中发生的情况:

$base = new Base(10);

$baseBase类的实例;它与该类的任何其他实例以及ChildA类的任何实例完全独立。

(new ChildA())->handle();

这会尝试在__construct类中运行ChildA方法;从Base继承的该方法的副本需要一个参数,但是您没有提供参数,因此会出现错误。希望您这样称呼它:

(new ChildA(10))->handle();

如果我们直接在子类中定义__construct,则可以为其指定不同数量的参数:

class ChildB extends Base {
    public function __construct() {
        // Do nothing
    }
    public function handle(){
        echo $this->var;
    }
}
(new ChildB())->handle();

但是现在我们遇到了另一个问题:Base类中的逻辑未运行,因此$this->var从未设置为任何东西。

这是我在上面简化过的地方。实际上,父方法__construct和子方法__construct都存在,它们只是彼此“隐藏”。您可以使用语法parent::method访问父副本。

因此,您可以使用不带参数的构造函数来创建子类,并在运行该构造函数时,以10的硬编码值运行基本构造函数:

class ChildC extends Base {
    public function __construct() {
        // Run the constructor in the Base class
        parent::__construct(10);
    }
    public function handle(){
        echo $this->var;
    }
}
(new ChildC())->handle();

答案 3 :(得分:-1)

您的new ChildA()正在从Base调用构造函数,并且您没有在此处传递任何参数。

您在这里犯了错误:执行new Base(10)时,您的$var不会传递给new ChildA()的新实例

在您的情况下,我将使用静态参数代替构造函数值

class Base {
    protected static $var;

    public function __construct(){
    }

    public static function setVar($var) {
        self::$var = $var;
    }
}

class ChildA extends Base {
    public function handle(){
        echo self::$var;
    }
}

Base::setVar(10);

(new ChildA())->handle();