+1  A: 

bar has a member variable named somethingelse, which is inherited from foo.

you are mixing object and class scope.

if you really want to achieve the effect described, you have to make your variable static, so its context is class based

knittl
+5  A: 

I thought that the child inherits all the data attributes and methods from the parent class.

This is true - the child class inherits the static variables and static methods from the parent class. Additionally, any child objects will inherit the static and instance variables and methods.

One possibility to get what you want with your existing class structure is this:

$bar = new Bar();
$bar->composition();// here you are calling the parent method, sets instance var $somethineelse
$bar->somethingelse->test();// now you can call methods

Another way to accomplish inheriting an variable (in this case an object) in child instances would be like so:

class Foo {
    protected $somethingelse;
    public function __construct() {
        $this->somethingelse = new SomethingElse();
    }
}

class Bar extends Foo {
    public function __construct() {
        parent::__construct();
        // now i've got $somethingelse
    }
 }

For a very good overview of classes and objects in PHP 5, take a look here: http://php.net/manual/en/language.oop5.php Make sure to read it all, maybe a couple times if OO is new for you.

ruquay
A: 

First, you have to distinguish between static and instance variables. Static variables are shared among all instances of a class, instance variables are not.

If you want every instance of Foo and Bar to have the exact same SomethingElse-Instance you have to make $somethingelse static:

public static $somethingelse

and you should change the composition-function of Foo:

function composition() {
    self::$somethingelse = new SomethingElse();
}

To access this static field you can do the following: $foo = new Foo(); // I am Foo $foo->composition(); // I am some other class Foo:$somethingelse->test(); // I am a method in the SomethingElse class

$bar = new Bar(); // I am Bar, my parent is Foo Bar::$somethingelse->test(); // I am a method in the SomethingElse class

If you want every instance of Foo and Bar have their own SomethingElse instance you can use your code, but you need to add

$bar->composition()

before $bar->somethingelse->test();

That's because with

$bar = new Bar();

you created a completely new instance of Bar and that instance has a $somethingelse property, but it has not been set yet. So you need to call composition() to set it.

If every Foo and Bar should have the exact same SomethingElse-instance, you should use the static version instead, because it reduces the memory needed.

I hope this can help you. Otherwise I am very happy to explain it further.

A: 

Saying that classes share attributes doesn't mean that the objects share attribute values.

As others have noted, you are confusing classes with instances.

Note, you'd get the same error if you did:

$foo = new Foo(); // I am Foo
$foo->composition(); // I am some other class
$foo->somethingelse->test(); // I am a method in the SomethingElse class

$foo2 = new Foo(); // I another Foo
$foo2->somethingelse->test(); // Fatal error: Call to a member function test() on a non-object

Think of the classes less abstractly. For example, you might have a class, "Person," which is a parent class of "Royalty."

Then if you did:

$me = new Person(); $me->firstName = "Thomas"

$princeCharles = new Royalty();

You wouldn't want $princeCharles to have the a firstName attribute equal to "Thomas," and if you want to set $princeCharles->firstName, you don't that to change the value of the firstName attribute of $me.

Both $me and $princeCharles have an attribute 'firstName', but we don't share the value of that attribute.

Thomas Andrews
A: 

I think your problem will be solved if in the derived class constructor will call the parent class constructor. This does not occur by default in PHP so keep it in mind when you have issues with inheriting data members.

class Bar extends Foo { public function __construct() { parent::__construct();

}

}

andreas