views:

162

answers:

2

Question edited to better reflect my needs.


Take the following example:

class Base
{
    public $Text = null;

    public function __construct()
    {
        $this->Text = new Base_Text();
    }
}

class Base_Text extends Base
{
    public $Is = null;

    public function __construct()
    {
        $this->Is = new Base_Text_Is();
    }

    public function CammelCase($string)
    {
        return trim(str_replace(' ', '', ucwords($string)));
    }
}

class Base_Text_Is extends Base_Text
{
    public function CammelCase($string)
    {
        return ($string === $this->CammelCase($string)); // doesn't work
    }
}

How can I fix the Base_Text_Is::CammelCase() method without calling the Base_Text class statically (not using parent:: or Base_Text::)?

The only solution I came up with for this kind of situations is to create a singleton function like this:

function Base()
{
    static $instance = null;

    if (is_null($instance) === true)
    {
        $instance = new Base();
    }

    return $instance;
}

And change the Base_Text_Is::CammelCase() method to this:

return ($string === Base()->Text->CammelCase($string));

And in order to avoid creating two object instances of the Base class, instead of doing:

$base = new Base();
$base->Text->Is->CammelCase('MethodOverloading'); // true

I just do:

Base()->Text->Is->CammelCase('MethodOverloading'); // true

Is this a good practice? Are there any other solutions?

+1  A: 

I don't think there is a way to call a parent method from the child with out calling it statically or using parent::. I may be misunderstanding the question though. Creating an instance of Son() doesn't create two objects. Son extends Dad but its still one object.

If you're going to call Dad() with a Singleton within Son then why extend it from Son?

Darrell Brogdon
I've updated my question with a more realistic example, please check it out.
Alix Axel
I still don't understand your aversion to using `parent::`.
Darrell Brogdon
It's not an aversion, I just can't use it because if I do I wont be able to access `Base_Text` non-static properties.
Alix Axel
+4  A: 

The heart of your question lies here:

How can Son::B() call the Dad::A() method non-statically (without using parent or Dad)?

The answer is simply, it can't. You overrode Dad::A() with Son::A(). The only concept of A() that the Son object now has is it's own A(). You would have to call the parent method statically, or on an altogether different Dad object instance.

The bottom line is, if you want to call the parent A() method, why are you bothering to override it in the first place?

Your structure doesn't make any sense either. Why would you want a call to $dad->A() pass it to $dad->son->A(), which in turn would call $dad->son->B(), which would then, from what you're asking, call $dad->A() again? That's an infinite loop.

Your singleton approach doesn't seem to offer any real advantage other than making sure you don't instantiate more than one dad object, but the fact is you're still instantiating an entirely separate object to perform logic that sounds like it should be inside the class and not outside.

Without seeing actual logic and what you're trying to accomplish, it's hard to know what to recommend to avoid this circular reliance. However, I think you might want to analyze what you're trying to do with these methods and perhaps redesign how the inheritance is working.

EDIT

I think you've got way too much inheritance going on. There is no reason you should be doing this:

$base = new Base();
$base->Text->Is->CammelCase('MethodOverloading'); // true

If all the functionality is in the child classes, you shouldn't be instantiating the Base class. It should be something like this:

$text = new Text();
$text->isCamelCase('someString');

Your code can be greatly simplified, with all the circular parent/child instantiations removed and the specific functionality pushed down to the child classes:

class Base
{
    //don't put anything related to child classes here,
    //unless it is going to provide specific functionality
}

class Text extends Base
{
    public function CamelCase($string)
    {
        return trim(str_replace(' ', '', ucwords($string)));
    }

    public function isCamelCase($string)
    {
        return ($string === $this->CamelCase($string));
    }
}
zombat
It's an hypothetical example of course, and I know it's an infinite loop. I've however encountered real world useful applications for this and I've always used the solution I provided in my question. I was just wondering if there could be any better alternative.
Alix Axel
I've updated the question to give a more realistic example and address some of the problems you refer, such as "instantiating an entirely separate object". Hope it makes it a little clearer now.
Alix Axel
@zombat: I would just like to ask, in light of my last edit, if you still think that redesigning the inheritance is a good idea (if yes, any pointers?) and if using the `Base()` singleton function is a bad practice in this scenario.
Alix Axel
Yes, your inheritance definitely needs to be redesigned. Your parent classes are all *relying on the existence of children classes*. This is not how inheritance is meant to be used. As well, child classes extend and replace the functionality of their parent classes. If a child overrides a method, you are saying "this is how this method is done now from this child on". I will make an edit to my answer.
zombat