Using composition over inheritance:
Instead of inheriting based on digestive system, break off digestion into its own set of classes.
First, an interface that describes different ways to eat.
public interface IDigest
{
void Eat(Meat food);
void Eat(Plant food);
void Eat(Offal food); //lol nethack
}
Carnivores eat meat, can eat herbs sometimes, and don't like crap:
public class Carnivorous : IDigest
{
public void Eat(Meat food)
{
Console.Write("NOM NOM");
}
public void Eat(Plant food)
{
if(Starving)
Console.Write("Ugh, better than nothing.");
else
Vomit();
}
public void Eat(Offal food)
{
Vomit();
}
}
Herbivores are picky and would rather die than eat meat (I know, save your comments, this is an example)
public class Herbivorous : IDigest
{
public void Eat(Meat food)
{
Vomit();
}
public void Eat(Plant food)
{
Console.Write("NOM NOM");
}
public void Eat(Offal food)
{
Vomit();
}
}
Omnivores eat anything. Witness a state fair.
public class Omnivorous : IDigest
{
public void Eat(Meat food)
{
Console.Write("NOM NOM");
}
public void Eat(Plant food)
{
Console.Write("NOM NOM");
}
public void Eat(Offal food)
{
Console.Write("NOM NOM");
}
}
All animals must eat, so they must have a digestive system, along with other systems.
public abstract class Animal
{
/* lots of other stuff */
public IConsume DigestiveSystem {get;set;}
/* lots of other stuff */
}
Hippies are an animal class with known tastes; it configures itself on instantiation. It is also possible to inject behaviors and systems from the outside.
public class Hippie : Animal
{
public Hippie()
{
/*stuff*/
DigestiveSystem = new Herbivore();
BodyOdorSystem = new Patchouli();
/*more stuff*/
}
}
And finally, let's see a hippie eat a burger.
public static void Main()
{
Hippie dippie = new Hippie();
Meat burger = new Meat("Burger", 2/*lb*/);
dippie.DigestiveSystem.Eat(burger);
}
When modeling complex systems like animals, I'd prefer composition over inheritance ANY DAY. Complex systems can explode an inheritance tree with the quickness. Take three animal systems: omnivore/herbivore/carnivore, water/air/land, and nocturnal/diurnal. Let's not even worry about how to decide which classification becomes the first point of differentiation for Animals. Do we extend Animal to Carnivore first, to WaterLiving first, or to Nocturnal first?
Since an omnivore can live in the air and prefer the night (bat*) and also be a day walking land creature (humans), you have to have an inheritance path that hits every single option. That's an inheritance tree with 54 different types already (its early, be kind). And Animals are much more complex than this. You could easily get an inheritance tree that had millions of types. Composition over inheritance, definitely.
*New Zealand Short Tailed bat, for example, is omnivorous.