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だけで、すぐにそれはラインコンストラクタをprotectedまたはprivateとして定義することはできません!どうして?

protected function __construct(){} 

に達する前と後でブラウザに送信されていたであろう、何もすべてを出力としてコードを解釈停止します。

とすぐ、私はちょうどすべてが正常に動作し

// protected function __construct(){} 

にそれを変更することで、アウトその行を取るよう!?

私はそれを知りません。

アイデア?

+1

あなたが例えばファイル、でPHPの開始タグを持っていますか彼らは '<?php'で始まりますか? CLIから 'php -l A.php'と' php -l B.php'を実行して、解析エラーがあるかどうか確認できますか? – Gordon

+1

__construct()メソッドは、クラスのインスタンスが作成されるときにpublic(public)にアクセスする必要があります(public)。 –

+0

あなたの擬似コードには明らかな問題がないので、実際のコードで問題が発生する可能性が最も高いです。 PHPの実行が停止してエラーメッセージが表示されない場合は、おそらく完全なエラー報告を有効にする必要があります。方法がわからない場合は、お気軽に詳細をお尋ねください。 –

答えて

12

これは私のマシンでも起こっているかどうかを確認するための簡単なテストファイルを作成しました。私は答えを見つけたと思います。

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

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

そのコードを実行しようとすると、私は致命的なエラーを取得:「PHP致命的なエラーを次のコードテイク)(アクセスレベルは棒に:: __コンストラクト中(Fooクラスのように)公共なければなりません/ home/berry/foo.php on line 12. "親が既にアクセスレベルを定義している場合、子クラスのアクセスレベルを変更することはできません。実際には多くの意味があります。つまり、PHPはどのコンストラクタを呼び出すべきかわからないでしょう。

サイドノートとして:あなたのコードを見て、BはAを伸ばし、AはBを使います。それはどうして私にとっては奇妙な構造のようですか?あなたが実際に欲しいと思っているのはcomposition, not inheritanceです。

+0

ねえベリー、あなたの答えをありがとう。私の答えに書いたように、私はAの保護された要素にアクセスし、Bをシングルトンにする必要があります。しかし、私が直面している「リファクタリング状況」のb/cでは、やや奇妙です。私は最良の選択肢を選んだのかどうかはわかりませんが、それは今のところ最も簡単なはずです。 – Raffael

+0

こんにちは。このデザインは奇妙なようです。他のクラスを使用する(関連のない)他のクラスの保護されたメソッドにアクセスする必要があるクラスが必要ですか?おそらくあなたは状況を説明することから利益を得ることができます。私たちはそれについて何か良いことがあるかどうかを見てください:) –

+0

PHPがこのように振る舞うのはどれほどの意味があるのでしょうか(議論の余地はありますか?https://bugs.php.net/ bug.php?id = 61970)。しかし、これに与えられた正式な理由は、Liskov Substitution Principleであり、基本クラスインスタンスが予想されるところでは、派生クラスのインスタンスが「適合」しなければならないと基本的に述べています。 – Peter

6

canは、コンストラクタをprotectedまたはprivateとして定義します。このコード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; 
    } 
} 

、プライベートコンストラクタはnewキーワードでインスタンスを作成することを防ぐが、PHPは致命的なエラー(それだけで実行を停止されません)をトリガします:

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

物事をまっすぐにする:そのコードはうまくコンパイルされません。そのコードはちゃんと解釈される;) –

+1

@Berry Langerak - 私は知っていた*私の言葉の選択は論争になるだろう:) –

+0

@ÁlvaroG. Vicario:あなたの言葉の選択は '論争'ではない、それは間違っている...-) – MarcoS

1

カスタム静的イニシエータを作成することができます。

<?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(); 
関連する問題