Reputation: 81
I have the below problem. Look my structure of code. This will be ok if all my derived classes have the same sequence of methods in Process(Animal a). But imagine I have Turtle class, that extends Animal and when Process(Animal a) is called the methods inside have to be in different order and class Turtle has some extra methods for example Sleep. What should I do in that case? Thanks
public class Animal
{
public virtual string Eat(){ return "I'm eating"; }
public virtual string MakeNoise() { return "I'm ";}
public virtual string Go() { return "I'm walking"; }
}
public class Dog : Animal
{
public override string Eat()
{
return string.Format("{0} {1}",base.Eat(),"a pie");
}
public override string MakeNoise()
{
return string.Format("{0} {1}",base.MakeNoise(),"barking");
}
}
public class Controller
{
public void Process(Animal a)
{
a.Eat();
a.MakeNoise();
a.Go;
}
}
public class Client
{
IList<Animal> animals= new List<Animal>(){Dog,Cat,Turtle,Mouse}; //all animals have base class Animal
Controller = new Controller();
foreach(Animal a in animals)
{
p.Process(a);
}
}
Upvotes: 0
Views: 160
Reputation: 4119
You have two options, the first one is extend the Process method. You can make a switch inside and define the order when a.GetType() == typeof(Turtle).
public class Controller
{
public void Process(Animal a)
{
if(a.GetType() == typeof(Turtle)
{
((Turtle)a).YourMethod();
}
else
{
a.Eat();
a.MakeNoise();
a.Go;
}
}
}
Or you can make the Animal class responsible for the Process method. The idea here I think is not make Animal class responsible of Process method. That is where Controller come in action. Try to use a decorator pattern or a Factory for each Animal, as @Brett said
Upvotes: 0
Reputation: 29207
Each animal has Eat
, MakeNoise
, and Go
, but the sequence varies by animal (plus some additional behaviors for some animals.) Will the sequence always be the same for the given animal? Is the only reason why they inherit from Animal
so that they can share the same base behaviors and only override when they need to?
If so then perhaps instead of a Process
method in a controller there should be an ExecuteBehaviors
method on the Animal
which can be overridden by individual animals.
public virtual void ExecuteBehaviors()
{
Eat();
MakeNoise();
Go();
}
And then if an animal needs a different sequence it can override that method. That seems to meet the description of your problem, to allow each animal to inherit behaviors but control their sequence and add new behaviors.
Then in your controller you can just call ExecuteBehavior
for each animal. That's real polymorphism at work. You can treat any instance of Animal
the same and call the same method on it whether it's a Dog
or a Turtle
, even though their behaviors will vary.
Upvotes: 0
Reputation: 1550
You could write yourself a Controller factory that will return an appropriate controller for a given animal. Create a sub-class of Controller for Turtle, etc. Here I've assumed that we can extract an interface IControler, and IAnimal, but you could use abstract base types instead.
public class ControllerFactory
{
public static IController GetController (IAnimal animalToControl)
{
if (animalToControl is Turtle) { return new TurtleController(); }
if (animalToControl is Sheep) { return new SheepController(); }
// default
return new Controller();
}
}
and call with:
foreach(Animal a in animals)
{
var p = ControllerFactory.GetController(a);
p.Process(a);
}
The implementation of the factory here is crude, but illustrates the point.
Upvotes: 0
Reputation: 13620
You can add an overloaded method
public void Process(Turtle t)
{
//Do what you want here
}
Upvotes: 2