0

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);
     }
}
1
  • 4
    This is changing the behaviour of the Controler, not the Animal, so you will need to create overriden types of that, e.g. TurtleController Commented May 16, 2016 at 13:55

4 Answers 4

2

You can add an overloaded method

   public void Process(Turtle t)
   {
      //Do what you want here
   }
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

0

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.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.