「A」と「B」の2つのクラスがあります。アプリケーションロジックでは、クラス「A」を除いて、クラス「B」のオブジェクトを作成することはできません。しかし、同じファイルに2つのクラスを含めたくないので、「プライベート」な性質でそれを制限することはできません。
この種の制限を作成することは可能ですか?「A」以外の誰かがクラス「B」のオブジェクトを作成しようとすると、あなたは腹を立てると言います!?
「A」と「B」の2つのクラスがあります。アプリケーションロジックでは、クラス「A」を除いて、クラス「B」のオブジェクトを作成することはできません。しかし、同じファイルに2つのクラスを含めたくないので、「プライベート」な性質でそれを制限することはできません。
この種の制限を作成することは可能ですか?「A」以外の誰かがクラス「B」のオブジェクトを作成しようとすると、あなたは腹を立てると言います!?
これは非常にハックであり、使用しないでください。私はハックなものが好きなので、投稿するだけです ;) さらに、E_STRICT
エラー報告が有効になっている場合、これはエラーをスローします:
class B
{
private function __construct() {}
public function getInstance() {
if (!isset($this) || !$this instanceof A) {
throw new LogicException('Construction of B from a class other than A is not permitted.');
}
return new self;
}
}
class A
{
function someMethod() {
$b = B::getInstance(); // note that I'm calling the non-static method statically!
}
}
これが機能する理由は、このマニュアル ページの 2 番目の例に見られる「機能」にあります。
バックトレースを調べることができます:
class B
{
public function __construct()
{
$chain = debug_backtrace();
$caller = $chain[1]['class'];
if ('A' != $caller) {
throw new Exception('Illegal instantiation');
}
}
}
たぶんあなたはこのようなものを使いたいでしょう:
class A
{
protected function __construct ()
{
}
}
class B extends A
{
public function __construct ()
{
$a = new A();
}
}
$b = new B();
B のコンストラクターで、A を渡す必要があります。次に、A から B を取得する場合は、B を作成して A を渡すだけです。新しい B が呼び出されると、A を渡す必要があります。
class A
{
private $b;
private function getB()
{
if (null === $this->b)
{
$this->b = new B($this);
}
return $this->b;
}
}
class B
{
public function __construct(A $a)
{
}
}
get_called_class
オブジェクトをインスタンス化しようとしているクラスを見つけるために使用します。
class B
{
public function __construct ()
{
if(get_called_class() != 'A') {
//booboo
}
}
}