简体   繁体   中英

Passing instances of a class without knowing the Type

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.

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();
    }
}

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM