PowerPuffGirl
PowerPuffGirl

Reputation: 81

Using virtual methods in C#

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

Answers (4)

Zinov
Zinov

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

Scott Hannen
Scott Hannen

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

Brett
Brett

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

David Pilkington
David Pilkington

Reputation: 13620

You can add an overloaded method

   public void Process(Turtle t)
   {
      //Do what you want here
   }

Upvotes: 2

Related Questions