0

This is a follow up question on the following answer : Parent Object in php

class A {
    protected function doSomeStuff(){
       echo 'a method that all children will need to call';
    }
}

class B {
    protected $_parent;
    public function __construct($parent) {
       $this->_parent = $parent;
    }
    public function doSomeLocalStuff() {
       $this->_parent->doSomeStuff(); // Fatal Error
    }
}

$a = new A(); // will be used for other children as well.
$b = new B($a);
$b->doSomeLocalStuff();

In the above code, parent object Injection was used, allowing class B to be initialized using a specific instance of class A, but class B wont be able to access class A protected properties or methods (e.g., doSomeStuff()).

But by mixing the above with inheritance, we get the best of both worlds :)

class B extends A {
    protected $_parent;
    public function __construct($parent) {
       $this->_parent = $parent;
    }
    public function doSomeLocalStuff() {
       $this->_parent->doSomeStuff(); // Works :)
    }
}

So, is this acceptable ? .. any drawbacks ?

P.S: I'm trying to implement a non-static factory pattern.

Clarification

Consider this, I'm trying to design a class which will be used for calling an external API. We've over 400 different calls, divided into 10 categories (billing, customers, products ... ).

All the 400 calls shares the same parent-url, username/password and some other common properties.

So, instead of putting the 400 method in one big class, I decided to divide them into 10 classes, with a parent class handling common functions (e.g., authentication, url construction, web call ... ), then created a factory pattern, where I can load only needed classes/categories on run-time.

Something like :

$apiCall = new parentPlusFactory(); 
          //contains common methods and a mechanism to load sub-classes
$apiCall->setAPIuserName("user");
$apiCall->setAPIpassword("pass");
$apiCall->useClass('customers')->doSomeCustomerStuff();
$apiCall->useClass('products')->doSomeProductStuff();

That's why I need to share the same parent class instance.

Community
  • 1
  • 1
Amr
  • 3
  • 2
  • I don't see why you would want to pass the parent to the constructor when you could just create a new B being an A. If you dont overwrite the methods of A in B you can just keep using them and if you need to add some stuff you can still access them with the parent keyword. – Dan Oct 02 '11 at 09:42
  • Well, I need to share the same **class A** instance across child classes. – Amr Oct 02 '11 at 14:01

2 Answers2

1

There is no friend keyword in PHP, like in C++. You could check this discussion for a way to implement friend classes.

But do you really need that function to be declared protected?

Griwes
  • 8,805
  • 2
  • 43
  • 70
  • As you mentioned, there's neither friend classes nor a solid work around in PHP. And that parent method must be protected as it has to be called by a child. – Amr Oct 01 '11 at 22:23
  • And it really couldn't be public? – Griwes Oct 01 '11 at 22:37
  • Yes, as the parent class holds the main logic, which doesn't make sense when called out of context/child classes. – Amr Oct 01 '11 at 22:47
  • **Class A** methods are a constructor for an API, where they contain the main logic (connection, username/password ..etc), while other child classes contains actual API methods. I'll try to clarify it more in the question body. – Amr Oct 02 '11 at 14:10
0

In general you should favor composition over inheritance. To me your use case sounds like B should not be extending A at all, but instead you should have two separate classes.

Now, PHP 5.4 will have "horizontal reuse", also known as "traits", where it will be possible to "include" a trait into your class.

trait A
{
    public function doSomeStuff()
    {
        echo 'doing some stuff';
    }
}

class B
{
    use A;

    public function doSomeLocalStuff()
    {
        $this->doSomeStuff();
    }
}

class C
{
    use A;

    public function doSomeLocalStuff()
    {
        echo 'Doing something completely different here';
    }
}

See also PHP manual: traits and PHP 5.4 beta1 released.

igorw
  • 27,759
  • 5
  • 78
  • 90
  • The only reason for extending A, is using its protected methods. A method handling api-web-calls in A should only be accessed by one of this specific api sub-classes. – Amr Oct 02 '11 at 15:00
  • On a second thought .. I'll try to re-design the class using only composition, as it seems the logical way to go. – Amr Oct 02 '11 at 16:18