2011-01-17 10 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 po prostu przestaje interpretacji kodu, jak tylko osiągnie linięnie można zdefiniować konstruktora jako chronionego lub prywatnego! czemu?

protected function __construct(){} 

i wyprowadza wszystko przed i nic, że zostały wysłane do przeglądarki później.

I tak szybko, jak tylko wziąć tę linię na zewnątrz, zmieniając go

// protected function __construct(){} 

wszystko działa w porządku !?

Nie rozumiem tego.

Wszelkie pomysły?

+1

Czy masz tagów otwarcia pHP w plikach, np zaczynają się od ' Gordon

+1

Metoda __construct() musi być publiczna, ponieważ jest dostępna (publicznie) po utworzeniu instancji klasy. –

+0

Twój pseudo-kod nie ma żadnego oczywistego problemu, więc problemy najprawdopodobniej występują w Twoim prawdziwym kodzie. Jeśli PHP przestanie działać i nie wyświetli żadnego komunikatu o błędzie, prawdopodobnie musisz włączyć pełne raportowanie błędów. Jeśli nie wiesz jak to zrobić, zapytaj o szczegóły. –

Odpowiedz

12

Właśnie utworzyłem prosty plik testowy, aby potwierdzić, że dzieje się to również na moim komputerze, i myślę, że znalazłem odpowiedź. Weźmy następujący kod:

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

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

Gdy próbuje wykonać ten kod, pojawia się błąd krytyczny: „PHP Fatal error: Poziom dostępu do Bar :: __ construct() musi być publiczne (jak w klasie Foo) w/home/berry/foo.php na linii 12. " Oznacza to, że nie można zmienić poziomu dostępu w klasie potomnej, jeśli rodzic już zdefiniował poziom dostępu, co w rzeczywistości ma sens: PHP nie wiedziałoby, który konstruktor wywoływać, jak sądzę.

Na marginesie: patrząc na twój kod, B rozszerza A, a A używa B. Dlaczego tak właśnie jest, wydaje mi się to dziwną konstrukcją? Domyślam się, że faktycznie chcesz, to composition, not inheritance.

+0

hej Berry, dziękuję za odpowiedź. Jak napisałem w mojej odpowiedzi, muszę uzyskać dostęp do elementów chronionych w A i potrzebuję B, aby był singletonem. Ale to jest trochę dziwne w czynach, b/c "sytuacji refaktoryzacyjnej", z którą stoję. Nie jestem pewien, czy wybrałam najlepszą opcję, ale myślę, że powinna być teraz najprostsza. – Raffael

+0

Witam. Ten projekt wydaje się dziwny. Potrzebujesz klasy, która potrzebuje dostępu do chronionych metod innej (niezwiązanej?) Klasy, która używa drugiej? Być może skorzystasz z wyjaśnienia sytuacji, sprawdź, czy jest coś dobrego, co możemy powiedzieć na jej temat :) –

+0

Myślę, że to dyskusyjne, jak wiele zmysłów sprawia, że ​​PHP zachowuje się w ten sposób (zobacz https://bugs.php.net/ bug.php? id = 61970). Oficjalną przyczyną tego jest Liskov Substitution Principle, która zasadniczo stwierdza, że ​​instancje klas pochodnych powinny "pasować" tam, gdzie spodziewana jest instancja klasy bazowej. – Peter

6

Możesz można zdefiniować konstruktora jako chronione lub prywatne. Ten kod kompilujeruns 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; 
    } 
} 

Oczywiście, prywatne konstruktorzy uniemożliwić utworzenie instancji ze słowem kluczowym new, ale PHP spowoduje błąd krytyczny (nie będzie po prostu przestać działać):

<?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

Tylko po to, aby wszystko było proste: ten kod nie skompiluje się w porządku. Ten kod będzie interpretowany bezbłędnie;) –

+1

@Berry Langerak - Ja * wiedziałem * mój wybór słów byłby polemiczny :) –

+0

@ Álvaro G. Vicario: twój wybór słów nie jest "polemiczny", to jest złe ... :-) – MarcoS

1

można tworzyć niestandardowe inicjatorów statycznych:

<?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(); 
Powiązane problemy