0

I want to know how to pass down instances of objects without knowing the Type that they are. I'd like to know this because if I have a 100 animal types, then I don't want to have a 100 if statements or a switch. I have provided a snippet, which is an example of what I want to basically achieve. Right now it obviously doesn't work where I put the comments at.

using System.IO;
using System;
using System.Collections.Generic;

class Program
{
    Dictionary<string, dynamic> myAnimals = new Dictionary<string, dynamic>();

    Program(){
        myAnimals.Add("Maggie", new Dog("Maggie"));
        myAnimals["Maggie"].bark();

        myAnimals.Add("Whiskers", new Cat("Whiskers"));
        myAnimals["Whiskers"].meow();

        animalClinic clinic = new animalClinic();
        clinic.cureAnimal(myAnimals["Whiskers"]);
    }

    static void Main()
    {
        new Program();
    }
}

class Dog{
    string name;

    public Dog(string n){
        name = n;
    }

    public void bark(){
        Console.WriteLine("\"Woof Woof\" - " + name);
    }
}

class Cat{
    string name;

    public Cat(string n){
        name = n;
    }

    public void meow(){
        Console.WriteLine("\"Meow Meow\" - " + name);
    }
}

class animalClinic(){
    public void cureAnimal(object animal){ //This is where I need some help.
        if(animal.name == "Maggie"){ //I know I can use 'animal.GetType() == ...' That isn't the point.
            Console.WriteLine("We heal fine dogs!"); //The point is to access various methods within the object.
        }else{//I know it kind of beats the point of Type-Safety, but this is only an example and another way to do this is perfectly fine with me.
            Console.WriteLine("Eww a cat!")
        }
    }
}

If anyone knows an alternative solution to this, then please go ahead and share!

Thanks.

EDIT: I think you'll also need to reference the animal instead of just passing it down.

4 Answers4

3

This is what polymorphism is for:

public interface IAnimal
{
     string name {get;set;}

     void speak();

     void cure();
}

public class Dog : IAnimal
{
    public Dog (string n)
    {
        name = n;
    }

    public string name {get;set;}

    public void bark() 
    {
        Console.WriteLine("\"Woof Woof\" - " + name);
    }

    public void speak() { bark(); }

    public void cure()
    { 
         Console.WriteLine("We heal fine dogs!"); 
    }
}

public class Cat : IAnimal
{
    public Cat(string n)
    {
        name = n;
    }

    public string name {get;set;}

    public void meow() 
    {
        Console.WriteLine("\"Meow Meow\" - " + name);
    }

    public void speak() { meow(); }

    public void cure()
    { 
         Console.WriteLine("Eww a cat!"); 
    }
}

class Program
{
    static Dictionary<string, IAnimal> myAnimals = new Dictionary<string, IAnimal>();

    static void Main()
    {
        myAnimals.Add("Maggie", new Dog("Maggie"));
        myAnimals["Maggie"].speak();

        myAnimals.Add("Whiskers", new Cat("Whiskers"));
        myAnimals["Whiskers"].speak();

        animalClinic clinic = new animalClinic();
        clinic.cureAnimal(myAnimals["Whiskers"]);
    }
}

public class animalClinic
{
    public void cureAnimal(IAnimal animal)
    { 
        animal.cure();
    }
}
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Why are you creating separate methods for each animal type explicitly in the animalClinic? Why not just have cureAnimal(IAnimal animal) and call animal.Description or whatever appropriate property? Looks like you're subverting the whole point of polymorphism here. – Jeb Dec 27 '14 at 18:32
  • I was trying to show both techniques... sometimes you want functionality like this to live in a different place in a code base. But this doesn't work anyway, as Dictionary doesn't support type variance. An edit is coming. – Joel Coehoorn Dec 27 '14 at 18:36
0

Create an interface (contains definitions for a group of related functionalities that a class or a struct can implement) called IAnimal which contains a Description property which returns "We heal fine dogs!" for your Dog class etc. Each of your concrete animal classes implement this interface meaning you can just call the Description property in your cureAnimal method.

Jeb
  • 3,689
  • 5
  • 28
  • 45
0

Use polymorphism.

public abstract class Animal
{
    public string Name { get; set; }

    public abstract void Cure();
}

public class AnimalClinic
{
    public void CureAnimal(Animal animal)
    {
        animal.Cure();
    }
}

public class Dog : Animal
{
    public override void Cure()
    {
        Console.WriteLine("We heal fine dogs!");
    }
}

If you want to define the Cure logic inside of the AnimalClinic class like you do now, you might have to perform conditional execution of some sort.

This conditional execution does not have to be as unwieldy as a massive if statement or even a switch. You can research alterantive solutions to if statements here on SO. In fact, Joel Coehoorn has supplied one.

Community
  • 1
  • 1
User 12345678
  • 7,714
  • 2
  • 28
  • 46
0

I believe the best option here is to use the strategy design pattern. Perfectly explained here http://www.dofactory.com/net/strategy-design-pattern

An example for your case is provided by ByteBlast and Joel Coehoorn's answers