What to do with methods if the methods do not make sense to all sub-classes?

Hello

What is the best way to deal with this situation?

All other classes (Tiger, Snake and Bird) are Animal but Tigers do not fly.

class Animal
	{
		private $name;

		
		public function fly()
			{

			}	

		public function run()
			{

			}	
				
		public function crawl()
			{
				
			}
		
	}


class Tiger extends Animal
	{
		//
	}

class Snake extends Animal
	{
		//
	}

class Bird extends Animal
	{
		//
	}

Eh no replies yet :slight_smile:

Would something like this be a good solution?

interface fly
	{
		public function fly();
	}
class fly_yes implements fly
	{
		public function fly()
			{
				return "Does fly";
			}	
	}	

class fly_no implements fly
	{
		public function fly()
			{
				return "Does not fly";
			}	
	}




class Animal
	{
		private $fly;
		public function __construct(fly $fly)
			{
				$this->fly = $fly;
			}
		public function fly()
			{
				echo $this->fly->fly();
			}	
	}
	

class Tiger extends Animal
	{
		
	}

$doesnt_fly = new fly_no();
$tiger = new Tiger($doesnt_fly);
echo $tiger->fly();

Do you plan on writing the body of the function out? Here’s some options:


class animal {
    public function run() {
        ...
    }

    public function crawl() {
        ...
    }
}

class tiger extends animal {

}

class bird extends animal {
    public function fly() {
        ...
    }
}

This is the point of extension, bird can use all of animals functions but fly is restricted to bird. There’s also interfaces… What’s your overall assignment so we can help you understand this.

Theres no practical use for your second solution…

Then you can redesign your class hierarchy a bit, it is what we call refactoring.

From here: http://learnpythonthehardway.org/book/ex44.html

In object-oriented programming, Inheritance is the evil forest. Experienced programmers know to avoid this evil because they know that deep inside the Dark Forest Inheritance is the Evil Queen Multiple Inheritance. She likes to eat software and programmers with her massive complexity teeth, chewing on the flesh of the fallen. But the forest is so powerful and so tempting that nearly every programmer has to go into it, and try to make it out alive with the Evil Queen’s head before they can call themselves real programmers. You just can’t resist the Inheritance Forest’s pull, so you go in. After the adventure you learn to just stay out of that stupid forest and bring an army if you are ever forced to go in again.

You could say the same thing about endless levels of abstraction.

The underlying issue seems to be that inheritance is hierarchical, but certain traits such as flying might not be. Fortunately PHP has a feature for this, called … wait for it … traits!

trait FlyingTrait
{
    public function fly()
    {
        // ...
    }
}

class Animal
{
    // A generic animal doesn't fly
}

class Bird extends Animal
{
    // But a bird does!
    use FlyingTrait;
}

class Squirrel extends Animal
{
    // A squirrel doesn't
}

class FlyingSquirrel extends Squirrel
{
    // But a flying squirrel would!
    use FlyingTrait;
}

Hi friend;

I think the problem with your solution is that if I have another class called Eagle for example and I want it to have exact same function fly, then I can’t.

According to your solution every single class that needs a fly method, should contain it within itself.

As in my solution we can have a global fly method in its specific fly class and pass it on to all the species who fly.

I am trying to learn SOLID using this and the other thread so I can make extendable use that follows all the principles. Already made a lot of progress thanks to this forum members.

Does it make sense to you?

Cheers

This is a good solution. Not sure if this is better or my solution. I found it in Heads First book. Any ideas?

This is where hierarchy really comes into inheritance. All these examples are animals, but bird is not a particular animal, but rather a type of animal. Therefore Eagle can extend bird…


class Animal {}

class Bird extends Animal {
    function fly() {}
}

class Eagle extends Bird {}

class Sparrow extends Bird {}


// Ostrich is a bird but it cannot fly.  Oops.
class Ostrich extends Bird();

// Penguins are birds but not only can they not fly but they can swim. Double oops.
class Penguin extends Bird();

Point being that inheritance is not a good solution for these sorts of problems.

What do you think about my solution in post #2 ? I am not sure if there are anythings that could go wrong with it. I am still a newbie.

Thanks

It does not scale. Even with just three traits it means that you have to pass three arguments when you create a tiger instance. Imagine 10 traits and 100 different types of animals.

Try rewriting such that the Tiger class decides if it can fly in it’s constructor.

Good point, well made. Where chained inheritance falls down in this way I think I personally would opt for Traits.

Hi;

But I am not using traits!