代码之家  ›  专栏  ›  技术社区  ›  Carson Myers

在PHP中声明类的ctor“final”是一个坏习惯吗?

  •  7
  • Carson Myers  · 技术社区  · 15 年前

    如果我有一个由许多其他类扩展的父类,并且我想确保父类的构造函数总是运行的,那么声明该构造函数是一个坏主意吗? final 是吗?

    我想做这样的事:

    class ParentClass {
    
        public final function __construct() {
    
            //parent class initialization...
    
            $this->construct();
    
        }
    
        protected function init() {
    
            echo 'constructing<br>';
    
        }
    
    }
    
    class ChildClass extends ParentClass {
    
        protected function init() {
    
            //child class initialization
    
            echo 'constructing child<br>';
    
        }
    
    }
    

    这样子类就可以有一种构造函数,而父类的构造函数将始终执行。这是不好的做法吗?

    3 回复  |  直到 8 年前
        1
  •  9
  •   Mike    15 年前

    声明一个 final __construct 确保扩展类的任何人都不能实现同名的方法。从表面上看,这似乎意味着没有其他人可以为此类的子类声明构造函数,但这不是真的,因为 ClassName() 仍然可以作为构造函数的备用名称。所以,实际上,将构造函数声明为final在PHP中什么也得不到。

        2
  •  5
  •   bstoney    8 年前

    从php 5.3.3开始,我已经用5.6和7.0测试了它,声明了 __construct 类的方法 final 将阻止任何子类重写构造函数 _构造 或php 4样式 ClassName() (注意,从php 7开始,php 4样式已被弃用)。阻止子类声明构造函数将确保始终调用父构造函数。当然,这将不允许任何子类实现自己的构造函数逻辑。尽管我不建议将其作为一般的良好实践,但肯定会有实际的用例。

    一些例子:

    不声明 _构造 最终的

    class ParentClassWithoutFinal {
        private $value = "default";
    
        public function __construct() {
            $this->value = static::class;
        }
    
        function __toString() {
            return $this->value;
        }
    }
    
    class ChildClassA extends ParentClassWithoutFinal {
        public function __construct() {
            // Missing parent::__construct();
        }
    }
    
    echo (new ChildClassA()); // ouput: default
    

    以最终 β-构造

    class ParentClassWithFinal extends ParentClassWithoutFinal {
        public final function __construct() {
            parent::__construct();
        }
    }
    
    class ChildClassB extends ParentClassWithFinal {
    }
    
    echo (new ChildClassB()); // output: ChildClassB
    

    试图申报 β-构造 在儿童班

    class ChildClassC extends ParentClassWithFinal {
        public function __construct() {
        }
    }
    
    // Fatal error: Cannot override final method ParentClassWithFinal::__construct()
    

    试图申报 类名() 子类中的构造函数

    class ChildClassD extends ParentClassWithFinal {
        public function ChildClassD() {
        }
    }
    
    // Fatal error: Cannot override final ParentClassWithFinal::__construct() with ChildClassD::ChildClassD()
    // Also in PHP 7: Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; ChildClassD has a deprecated constructor
    
        3
  •  -1
  •   Valentin Golev    15 年前

    完成构造函数后,不能向初始化函数传递任何变量。它强制您类的用户使用全局变量作为其子类的设置。

    在Zend框架中,使用可重写的init()是常见的做法,但我从未见过在那里完成构造函数。