2011-01-17 9 views
8
--- A.php ---- 
require_once 'B.php'; 

class A 
{ 
    public function __constructor($x){...} 

    public function foo() 
    { 
     $b = B::getInstance(); 
     ... 
    } 
} 

--- B.php ---- 
require_once 'A.php'; 

class B extends A 
{ 
    protected static $_instance = null; 

    protected function __construct(){} 

    public static function getInstance() 
    {....} 
} 

PHP sólo se detiene interpretar el código tan pronto como se alcanza la línea deno se puede definir el constructor como protegido o privado. ¿por qué?

protected function __construct(){} 

y da salida a todo antes y nada de lo que habría sido enviada al navegador después.

Y tan pronto como me tomo esa línea, cambiándola a

// protected function __construct(){} 

todo funciona bien !?

No entiendo eso.

¿Alguna idea?

+1

¿tiene etiquetas de apertura de PHP en los archivos, por ejemplo, comienzan con ' Gordon

+1

El método __construct() deberá ser público ya que se accede (públicamente) cuando se crea una instancia de la clase. –

+0

Su pseudocódigo no tiene ningún problema obvio, por lo que es muy probable que el problema esté en su código real. Si PHP deja de ejecutarse y no muestra ningún mensaje de error, es probable que deba habilitar el informe completo de errores. No dude en solicitar detalles si no sabe cómo hacerlo. –

Respuesta

12

Acabo de crear un archivo de prueba simple para confirmar si esto sucede en mi máquina también, y creo que he encontrado la respuesta. Tomemos el siguiente código:

<?php 
error_reporting(E_ALL | E_STRICT); 
class Foo { 
    public function __construct() { 
    } 
} 

class Bar extends Foo { 
    protected function __construct() { 
    } 
} 

, se intenta ejecutar ese código, me sale un error fatal: "PHP Fatal error: Nivel de acceso a Bar :: __ construct() debe ser público (como en la clase Foo) en/home/berry/foo.php en la línea 12. " Eso significa que no puede cambiar el nivel de acceso en una clase secundaria, si el padre ya ha definido el nivel de acceso, lo que realmente tiene mucho sentido: PHP no sabría a qué constructor llamar, supongo.

Como nota al margen: al mirar su código, B se extiende A, y A usa B. ¿Por qué exactamente es así, me parece una construcción extraña? Supongo que realmente quieres es composition, not inheritance.

+0

hey Berry, gracias por su respuesta. Como escribí en mi respuesta, necesito acceder a los elementos protegidos en A y necesito que B sea un singleton. Pero es algo extraño en realidad, b/c de la "situación de refactorización" a la que me enfrento. No estoy seguro si escogí la mejor opción, pero debería ser la más sencilla por ahora, creo. – Raffael

+0

Hola. Este diseño parece ser extraño. Necesita una clase que necesite acceso a los métodos protegidos de una clase diferente (¿no relacionada?), Que utiliza la otra clase? Quizás te beneficie al explicar la situación, ver si hay algo bueno que podamos decir al respecto :) –

+0

Creo que es discutible el sentido que tiene para PHP comportarse de esta manera (ver https://bugs.php.net/ bug.php? id = 61970). Pero la razón oficial dada para esto es el Principio de Sustitución de Liskov, que básicamente establece que las instancias de clases derivadas deben "ajustarse" donde se espera una instancia de clase base. – Peter

6

Usted puede definir un constructor como protegido o privado. Este código se compila runs just fine since OOP was rewritten for PHP/5:

<?php 

class A{ 
    public function __construct(){ 
     echo 'Instance of A created' . PHP_EOL; 
    } 
} 

class B{ 
    protected function __construct(){ 
     echo 'Instance of B created' . PHP_EOL; 
    } 
} 

class C{ 
    private function __construct(){ 
     echo 'Instance of C created' . PHP_EOL; 
    } 
} 

Por supuesto, los constructores privados que impiden la creación de una instancia con la palabra clave new, pero PHP desencadenará un error fatal (que no sólo dejarán de publicarse):

<?php 

new A; // OK 
new B; // Fatal error: Call to protected B::__construct() from invalid context 
new C; // Fatal error: Call to private C::__construct() from invalid context 
+1

Solo para aclarar las cosas: ese código no compilará bien. Ese código será interpretado muy bien;) –

+1

@Berry Langerak - I * sabía * mi elección de palabra sería polémica :) –

+0

@ Álvaro G. Vicario: su elección de palabra no es 'polémica', está mal ... :-) – MarcoS

1

puede crear iniciadores estáticas personalizadas:

<?php 

class FancyClass { 
    public static function init() { 
     new self(); 
    } 

    protected function __construct() { 
     echo 'Instance created!'; 
    } 
} 

# This will not work. 
new FancyClass(); 

# But this will work. 
FancyClass::init(); 
Cuestiones relacionadas