Question

I'm trying to get the following to work, but I'm at a loss...

class Foo {
    public $somethingelse;

    function __construct() {
        echo 'I am Foo';
    }
    function composition() {
        $this->somethingelse =& new SomethingElse();
    }
}
class Bar extends Foo {
    function __construct() {
        echo 'I am Bar, my parent is Foo';
    }
}
class SomethingElse {
    function __construct() {
        echo 'I am some other class';
    }
    function test() {
        echo 'I am a method in the SomethingElse class';
    }
}

What I'd like to do is create an instance of the SomethingElse class within the class Foo. This works using =&. But when I extend class Foo with class Bar, I thought that the child inherits all the data attributes and methods from the parent class. However, it seems that $this->somethingelse doesn't work in child class Bar:

$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(); // Fatal error: Call to a member function test() on a non-object

So, is it not possible to inherit in such a way? And should I create a new instance of class SomethingElse from within class Bar if I want to use it there? Or am I missing something?

Thanks in advance for your help.

Was it helpful?

Solution

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.

OTHER TIPS

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

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.

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.

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();

}

}

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top