Page 1 of 1

State pattern. PHP missing friend class option.

Posted: Wed Jan 10, 2007 1:51 am
by jmut
Ok...I see some patterns are not really applicable in PHP because there is no `friend class` concept in php as in C++ for example.
In short a class A which is a friend of class B in C++ have access to private methods in class B.

State pattern is one that suffers from this in PHP. One implementation of the pattern suggest that context is passed as an arguament to each state but problem then is state does not really have full control over the context. Of course private methods could become public but problem then is that not only states will have access to guts of the context but outside world as well.

Found simple UML diagram to depict the issue.
setState() there in some cases could be called from within a state....but revealing method as public is a disaster.

What do you think? Someone come with a solution on that issue you don't consider this a problem?

Posted: Wed Jan 10, 2007 2:22 am
by Chris Corbyn
I'm not familiar with the pattern, but by the sounds of it PHP needs namespace support for this to work properly.

Posted: Wed Jan 10, 2007 2:35 am
by jmut
d11wtq wrote:I'm not familiar with the pattern, but by the sounds of it PHP needs namespace support for this to work properly.
If having namespace also mean that will be possible to declare class private (accessible only by the namespece/package) then yes.

Otherwise don't see how namespace will prevent someone from tweaking the context class accessing it with namespace::$context->publicMethod()

Posted: Wed Jan 10, 2007 3:09 am
by Christopher
Certainly other languages implement the State pattern without C++'s friend relationship. You could certainly define the methods as protected and then extend the context class for use with the State pattern with public methods.

Posted: Wed Jan 10, 2007 4:09 am
by Jenk
Kind of hackish.. but what about:

Code: Select all

class A implements friendship
{
    public function doSomething($b)
    {
        $b->doSomethingElse($this);
    }
}

class B
{
    public function doSomethingElse(friendship $obj)
    {
        $this->doSomethingWithFriendlyObject($obj);
    }
}

$a = new A;
$b = new B;

$a->doSomething($b);
EDIT: Or just plain interface type hinting without all the fuss, now I come to think of it.

Posted: Wed Jan 10, 2007 5:27 am
by jmut
Jenk: really nice...this could actually do the trick.