2010-01-03 35 views
7

如果我有一个由许多其他类扩展的父类,并且我想确保父类的构造函数总是运行,那么声明构造函数final是个坏主意?在PHP中声明类的ctor'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>'; 

    } 

} 

这样子类可以有一个排序的构造函数,父类的构造函数都会被执行。这是不好的做法吗?

+0

我明白你为什么不信任PHP程序员申报ClassName()构造函数,但我不明白为什么你关心:-) – 2010-01-03 03:28:41

+0

我只是想要明确我的代码 – 2010-01-03 10:56:02

回答

9

声明一个final__construct确保没有人扩展你的类可以实现一个同名的方法。从表面上看,这似乎意味着没有其他人可以为这个类的子类声明一个构造函数,但这不是事实,因为PHP 4风格的ClassName()仍然可以很好地作为构造函数。所以真的,声明一个构造函数为最终在PHP中没有任何东西。

+0

这是真的,我没有考虑到这一点。父类的__construct方法仍然会被调用吗?或者不同名称的子类的构造函数是否会覆盖它? – 2010-01-03 10:55:28

+1

父构造函数永远不会自动调用。您仍然必须在子类构造函数中调用'parent :: __ construct()'或'parent :: ClassName()'。 – Mike 2010-01-03 17:01:20

-1

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

在Zend框架中使用可重写的init()是很常见的做法,但我从来没有见过在此处定义构造函数。

+0

真的吗?我只是试过了,我可以将一个变量从finalized构造函数传递给子初始化函数并回显它 – 2010-01-03 01:32:22

+1

哦,我的意思是,用户不能通过任何未知的参数 – 2010-01-03 02:48:09

+0

但是,ZF正在转移到传递配置对象作为一种手段标准化参数如何在对象之间传递。 – 2010-01-03 03:09:34

3

由于PHP 5.3.3,我有5.6和7.0测试此,声明类final__construct方法将防止任何儿童类中重写或者使用__constructClassName()的PHP 4的风格构造(注意,自PHP 7起,PHP 4风格已弃用)。防止声明构造函数的子类将确保始终调用父构造函数。这当然不会允许任何子类实现自己的构造函数逻辑。虽然我不会推荐它作为一般的良好实践,但肯定会有实际用例。

一些例子:

不宣__construct最终

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 

随着最后__construct

class ParentClassWithFinal extends ParentClassWithoutFinal { 
    public final function __construct() { 
     parent::__construct(); 
    } 
} 

class ChildClassB extends ParentClassWithFinal { 
} 

echo (new ChildClassB()); // output: ChildClassB 

试图在一个子类来声明__construct

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 
相关问题