【问题标题】:why do we still need parent constructor when controller class extends a parent controller?当控制器类扩展父控制器时,为什么我们仍然需要父构造函数?
【发布时间】:2013-02-10 09:57:27
【问题描述】:

我是 CodeIgniter 和 OOP 的初学者。我正在阅读一页 CI 教程 here。我发现了一些问题。
看这段代码:

<?php
class News extends CI_Controller {
    public function __construct()
    {
        parent::__construct();
        $this->load->model('news_model');
    }

我认为如果我们创建一个扩展 CI_Controller 的类,我们假设它必须在其父类中具有所有方法和属性(尽管我们可以覆盖它们)。那么,为什么代码中有parent::__construct();呢?

【问题讨论】:

    标签: php codeigniter class inheritance


    【解决方案1】:

    __construct() 是类的构造方法。如果您从中声明一个新的对象实例,它就会运行。然而,如果一个类实现了它自己的__construct(),PHP 将只运行它自己的构造函数,而不是它的父类的构造函数。例如:

    <?php
    
    class A {
      public function __construct() {
        echo "run A's constructor\n";
      }
    }
    
    class B extends A {
      public function __construct() {
        echo "run B's constructor\n";
      }
    }
    
    // only B's constructor is invoked
    // show "run B's constructor\n" only
    $obj = new B();
    
    ?>
    

    在这种情况下,如果需要在声明 $obj 时运行类 A 的构造函数,则需要使用 parent::__construct()

    <?php
    
    class A {
      public function __construct() {
        echo "run A's constructor\n";
      }
    }
    
    class B extends A {
      public function __construct() {
        parent::__construct();
        echo "run B's constructor\n";
      }
    }
    
    // both constructors of A and B are invoked
    // 1. show "run A's constructor\n"
    // 2. show "run B's constructor\n"
    $obj = new B();
    
    ?>
    

    在 CodeIgniter 的例子中,该行运行 CI_Controller 中的构造函数。该构造函数方法应该以某种方式帮助您的控制器代码。而你只希望它为你做所有事情。

    【讨论】:

    • 您的 b 声明在扩展中缺少父级
    • 那么我们是否需要对新类中的其他方法执行相同的操作,这些方法在父类中具有类似的方法并希望使用它们的父功能?或者这仅适用于__construct() 类?
    • @MohammadBagherSaberi 视实际情况而定。如果不覆盖父类的方法,则不需要做parent::some_method()。即使您确实覆盖了父母的方法,也不必这样做。该模式为您提供重用代码和节省时间的方法。这不是限制。
    【解决方案2】:

    通过关键字extends 使用继承。父类在调用其构造函数时可能正在设置一些值。如果不调用父构造函数,则不会设置值,子类将不会获取这些值。

    例子:

    class Super {
        protected $a;
    
        public function __construct(){
            $this->a = 'Foo';
        }
    }
    
    class Child extends Super{
        protected $b = 'Bar';
    
        public function __construct() {
            parent::__construct();
            echo $this->a;
        }
    }
    
    $x = new Child();
    

    这里,如果父构造函数没有被调用,Child 类不会回显任何内容。

    因此,在 Codeigniter 中,父类可能会在您调用其构造函数时设置一些对其子类有帮助的值,而这些值仅在调用父构造函数时对其子类可用。

    【讨论】:

      【解决方案3】:

      我认为调用父构造函数/方法的需要是一种代码气味,称为Call super。除了错误敏感性(忘记这个调用,你会得到意想不到的结果),它是程序性的,而不是 OOP。毕竟,语句的顺序也会导致意想不到的结果。

      在此处阅读更多信息:https://martinfowler.com/bliki/CallSuper.html

      【讨论】:

        【解决方案4】:

        用于所有类的扩展。 __construct() 用于您使用的那个类。

        具有构造函数方法的类在每个新创建的对象上调用该方法,因此它适用于对象在使用之前可能需要的任何初始化。

        【讨论】:

          【解决方案5】:

          直接从 Code Iginiter 文档中回答您的问题:

          之所以需要这一行是因为您的本地构造函数将覆盖父控制器类中的构造函数,因此我们需要手动调用它。

          http://ellislab.com/codeigniter/user-guide/general/controllers.html#constructors

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-03-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-03-02
            • 2022-11-24
            相关资源
            最近更新 更多