Page 1 of 1

Calling a Class inside a Class

Posted: Tue Sep 14, 2004 12:17 pm
by bdeonline
Can I do that and is it just like calling a regular class? I know the extends to add a class but I am needing to add 2 classes.

Posted: Tue Sep 14, 2004 1:44 pm
by markl999
Yes, you can do that.
You could always try it too? ;)

Posted: Tue Sep 14, 2004 1:51 pm
by qads

Code: Select all

<?php
class a
{
var $b;
function say()
{
echo $this->b->foo();
}
}
//
class b
{
function foo()
{
return "u foo";
}
}
//
$a = &NEW a();
$b = &NEW b();
$a->b = &$b;
$a->say();
?>
thats how i use it, havent really checked with phpdn guys, so i am not sure if its a smart way to do it :P.

Posted: Tue Sep 14, 2004 3:28 pm
by McGruff

Code: Select all

/*
    Aggregation:
*/
class A
{
    function A(&$aggregated_class)
    {
        $this->aggregated_class =& $aggregated_class;
    }

    function foo()
    {
        // accesses $aggregated_class interface
    }

}
$an_object      =& new WhateverItIs();
$another_object =& new A($an_object);
$another_object->foo();


/*
    Composition (the Factory pattern)
*/
class B 
{
    function B()
    {
        $this->_setFactoryObject();
    }

    function foo()
    {
        // accesses $factory_object interface
    }
    
    //////////////////////////////////////////
    //              PRIVATE                 //
    //////////////////////////////////////////
        
    function _setFactoryObject()
    {
        $this->factory_object =& new WhateverItIs();
    }

}

$object =& new B;
$object->foo();
Aggregation and composition are different ways to associate classes. Notice how, with the second example, WhateverItIs is not exposed in the calling script. In OOP design, you generally want to minimise scope as much as possible in order to isolate discrete responsibilities in their own little module.

That's not to say that aggregation is bad - not at all. WhateverItIs might need to be accessed by several objects in the calling script, or may need to be configured before being associated, so hiding it inside a single class wouldn't be appropriate.

Don't try to associate classes with inheritance. Aggregation is almost always preferred if it's possible. Keep inheritance for cases where one object really is of the same type as the superclass.

Useful links:

http://www.phppatterns.com/index.php/ar ... ew/15/1/1/
http://www.phppatterns.com/index.php/ar ... ew/49/1/1/

phpPatterns has several other articles on design patterns & OOP in php.

There's an (experimental) example of inheritance and aggregation in action here: viewtopic.php?t=25959.

If you are exploring OOP I can't recommend strongly enough that you start unit testing as soon as possible - see the link in my signature.

Instantiation of the factory class in the second example is in its own method to make testing easier.

Posted: Tue Sep 14, 2004 3:36 pm
by feyd
McGruff wrote:

Code: Select all

class A
{
    function A($aggregated_class)
    {
        $this->aggregated_class =& $aggregated_class;
    }

    function foo()
    {
        // accesses $aggregated_class interface
    }

}
$an_object      =& new WhateverItIs();
$another_object =& new A($an_object);
$another_object->foo();
wouldn't A::aggregated_class be a reference to a copy of an object of WhateverItIs? (PHP4) Shouldn't A's constructor take a reference to first argument?

Posted: Tue Sep 14, 2004 3:42 pm
by McGruff
Well spotted - I've added the reference now.

That's what happens when you don't write the test first.. ;)