近日在编写继承性的PHP代码时,遇到一个怪异的问题,就是继承于另外一个基类的继承类的构造函数不能声明为private(但可以是protected和public,没有继承时也是可以使用private的),问题详细描述如下:
原来正常工作代码:
查看代码 PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?php class ClassB { /** * constructor */ private function __construct() { } /** * destructor */ public function __destruct() {} public function printit() { echo 'print it in ClassB.<br />'; } private static $instance = null; public static function getInstance() { if ( self::$instance==null ) { $c = __CLASS__; self::$instance = new $c; } return self::$instance; } } $objB = ClassB::getInstance(); $objB->printit(); ?> |
输出:
print it in ClassB.
加入继承后:
查看代码 PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?php class ClassA { /** * constructor */ protected function __construct() {} /** * destructor */ public function __destruct() {} public function printit() { echo 'print it in ClassA.<br />'; } } class ClassB extends ClassA { // <strong>加入继承</strong> /** * constructor */ private function __construct(){ } /** * destructor */ public function __destruct() {} public function printit() { echo 'print it in ClassB.<br />'; } private static $instance = null; public static function getInstance() { if ( self::$instance==null ) { $c = __CLASS__; self::$instance = new $c; } return self::$instance; } } $objB = ClassB::getInstance(); $objB->printit(); ?> |
输出:no work, 没有任何输出。
正确运行版本:
查看代码 PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?php class ClassA { /** * constructor */ protected function __construct(){} /** * destructor */ public function __destruct() {} public function printit() { echo 'print it in ClassA.<br />'; } } class ClassB extends ClassA { /** * constructor */ public function __construct(){ // <strong>也可以用protected</strong> } /** * destructor */ public function __destruct() {} public function printit() { echo 'print it in ClassB.<br />'; } private static $instance = null; public static function getInstance() { if ( self::$instance==null ) { $c = __CLASS__; self::$instance = new $c; } return self::$instance; } } $objB = ClassB::getInstance(); $objB->printit(); ?> |
回顾三个成员变量和方法修饰符的作用:
public : 被修饰的成员变量或方法可以在任何范围内(通过对象引用符或者类限定符)被访问或调用
protected : 被修饰的成员变量或方法可在本类内、继承类内被访问或调用,不能在本类和继承类外被访问或调用
private : 被修饰的成员变量或方法仅可在本类内被访问或调用,不能从继承类中访问或调用
上述现象似乎并没有跟上面的规定相抵触,但在继承类中使用private于构造函数就是不行。具体原因我还不得而知,知道者还望告知一下,^_^
很简单, 构造函数是在你的类 new的时候, 就开始使用了, 如果,你在构造函数里使用private, 那么与他的理论就起冲突了。
嗯,有道理。。。thx
细想了一下,这样的解释似乎不对。
的确,“构造函数是new类的时候”就开始调用了,但构造函数设定为private应该是可行的吖,因为就想限定调用者使用new生成ClassB的实例,只能使用getInstance来获得一个单例。
这样做在非继承类里是可以的,如第一段代码所示。但在继承类里就不行了。