I got two classes, "A" and "B". In the application logic no one is allowed to create an object of class "B", except for class "A".
But, since I dont want to have the two classes in the same file I cant restrict it with the "private" properity.
Is it possible to create this kind of restriction? If someone other then "A" tries to create an object of class "B", you say piss off!?
This is as hacky as it get's and you should not use it. I only post it, because I like hacky things ;) Furthermore this will throw an error if E_STRICT
error reporting is enabled:
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!
}
}
The reason why this works is a "feature" which may be seen in the second example of this manual page.
You could inspect the backtrace:
class B
{
public function __construct()
{
$chain = debug_backtrace();
$caller = $chain[1]['class'];
if ('A' != $caller) {
throw new Exception('Illegal instantiation');
}
}
}
In the constructor of B, require that A be passed in. When you then want to get B from A, just create a B and pass in A. When new B is called, it will require A be passed in.
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)
{
}
}
Maybe you want to use something like this:
class A
{
protected function __construct ()
{
}
}
class B extends A
{
public function __construct ()
{
$a = new A();
}
}
$b = new B();
Use get_called_class
to find out which class tries to instantiate an object:
class B
{
public function __construct ()
{
if(get_called_class() != 'A') {
//booboo
}
}
}