1

Here's something that I've been thinking about for some time. I want to chain together a set of methods like in the below shown example.
The concept of method chaining is no brainer, but what I want is to make all of our animals be added through the same add method, so how should I figure out what type of animal that we're adding inside the add method?

$zoo = new Zoo;
$lion = $zoo->lion->add('Lucas the lion');
$cockatoo = $zoo->cockatoo->add('Chris the cockatoo');

class Zoo {

    function add($name) {
        //How to figure out if the animal is a Lion or an Cockatoo?
    }

}
5
  • 3
    Why not $zoo->add(new Lion('Lucas'));? Where class Lion implements IAnimal {} Commented Feb 22, 2011 at 14:16
  • 1
    I can't stand chaining like that. I think it completely kills readability and makes your code ambiguous. If you must, I would suggest changing it to something like this: $zoo->add(new Lion('Lucas the Lion')); It decouples the Lion class from the Zoo class, and allows you to be far more flexible... Commented Feb 22, 2011 at 14:17
  • if($item instanceof Lion){ /* do something with lions */ } Commented Feb 22, 2011 at 14:17
  • @thephpdeveloper : Where did the $item originate? Commented Feb 22, 2011 at 14:24
  • $item, assuming that your parameter $name is changed to $item Commented Feb 22, 2011 at 15:04

2 Answers 2

1

Since we're talking about Object Oriented Design it would be much more "correct" and flexible to implement hierarchy like:

interface IAnimal {}
class Lion implements IAnimal {}

class Zoo
{
    private $animals = array();

    public function add(IAnimal $animal)
    {
        $this->animals[] = $animal;
        return $animal;
    }
 }

 $zoo = new Zoo();
 $lion = $zoo->add(new Lion('Lucas'));
Sign up to request clarification or add additional context in comments.

5 Comments

@Industrial: yep, I hope it is ;-)
I don't see how it adds more flexibility? Covering code in objects doesn't add anything (at least in this example). If you had some more data about the animal you wanted to hide, then maybe it would be worth it.
@Yacoby: it is the minimal sample that can give a hint to OP what to do next. I can't give any comprehensive code without more details.
But it does. It means that the Zoo::add method has type hinting for the interface IAnimal. You could achieve the same thing with an Animal parent class that implemented IAnimal and inherit from there or even by skipping the interface.
@Abba Bryant: I cannot get what you mean, sorry.
0

One solution to the problem would be to override __get in the Zoo class to return a 'creator' class.

function __get($animal){
    return new Creator($this, $animal);
}

Then let the creator class call the add function in the zoo class.

class Creator{
    public function __construct($zoo, $animal){
    ....
    }
    public function add($details){
        $zoo->add($this->_animal, $details);
    }
}

This solution is fairly ugly, and from a future developers perspective, not that clear. As pointed out in the comments, there are better ways about going this. Doing something like:

$zoo->add('lion', 'whatever')

or

$zoo->add( new Lion('Whatever') )

May be a better solution and in my opinion it is far clear to other developers what is happening. (This may not be the case for you, as I don't know the details of exactly what you are doing).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.