2

Assume the follwing classes:

public class Animal
{
}

public class Dog : Animal
{
     public void Bark()
     {
     }
}

public class Cat : Animal
{
     public void Meow()
     {
     }
}


Animal cat = Cat();
Animal dog = Dog();
PatternIamLookingFor.DoSomething(cat); // -> Call Meow
PatternIamLookingFor.DoSomething(dog); // -> Call Bark

Is this possible? Without adding a method like MakeNoise() to the Animal base class?

In my Application I have a CatFactory and a DogFactory, which implement AnimalFactory and return Animals. I cant call Meow/bark in the factory and I cant call it after I got the animals.

1
  • As @Reed suggested, you cant do this w/o reflection. If you did reflect however, you could simply add an attribute to your Bark and Meow methods, perhaps called [MakeNoise] that would allow for different method names. Commented Sep 30, 2013 at 20:06

5 Answers 5

2

I can think of a couple ways you could implement something like the above.

1. Use Interfaces

If you can modify the original source code, this is probably the best option. Easy to implement, easy to maintain.

public interface IDoSomething
{
    void DoSomething();
}

public class Dog : Animal, IDoSomething
{
     public void Bark()
     {
     }

     void IDoSomething.DoSomething(){
         Bark();
     }
}

public class Cat : Animal, IDoSomething
{
     public void Meow()
     {
     }

     void IDoSomething.DoSomething(){
         Meow();
     }
}

2. Use Adapters

If you don't have access to the original source code, adapters may be the only option. You could use them to "synchronize" the the way your code accesses your Cat and Dog classes. You can still work with the adapter as if it were the original object, but with a modified interface that better fits the needs of your new code. It would be fairly simple to create a factory to create the appropriate adapter based on parent type.

public IDoSomething
{
    void DoSomething()
    {
    }
}

public DoSomethingFactory
{

    public static IDoSomething( Animal parent )
    {
        if ( typeof( parent ) is Dog )
            return new DoSomethingDog( parent as Dog );
        if ( typeof( parent ) is Cat )
            return new DoSomethingCat( parent as Cat );
        return null;
    }

}

public DoSomethingDog : Dog, IDoSomething
{
    Dog _parent;
    public DoSomethingDog( Dog parent )
    {
        _parent = parent;
    }

    public void DoSomething()
    {
        _parent.Bark();
    }
}

public DoSomethingCat : Cat, IDoSomething
{
    Cat _parent;
    public DoSomethingCat( Cat parent )
    {
        _parent = parent;
    }

    public void DoSomething()
    {
        _parent.Meow();
    }
}

Aside from these two obvious implementations, you might want to consider these:

  • Use Decorators to enhance the capabilities of your classes dynamically. (Similar to the "wrapper" approach above, but baked into the class structure a little more cleanly.)

  • Implement a series of Command objects that your classes could handle dynamically:

    cat.Do( new MakeNoiseCommand() ); // Handled as "meow"
    dog.Do( new MakeNoiseCommand() ); // Handled as "bark"
    
  • Allow something similar to a Mediator to forward the requests based on the Animal's type, etc:

    public class AnimalMediator
    {
        public void MakeNoise( Animal animal )
        {
            if ( typeof( animal ) is Dog ) (animal as Dog).Bark();
            else if ( typeof( animal ) is Cat ) (animal as Cat).Meow();
        }
    }
    
Sign up to request clarification or add additional context in comments.

Comments

2

Is this possible? Without adding a method like MakeNoise() to the Animal base class?

Not without using reflection, dynamic, or some other runtime-based search of the method to call. The classic polymorphism-based approach would be to have a common method (like your MakeNoise()) in the Animal class.

5 Comments

Why polymorphism or dynamic? Just switch on Type().
@JeroenvanLangen Yes - but if the method doesn't exist, it'll throw at runtime. (I also wouldn't cause it evil ;) )
Oo why would you do that (reflection/dynamics) if you can simply implement interfaces?
@Ela You wouldn't, normally - you'd make a single method that's common, so you could use the interface. This question was saying specifically that he didn't want to add it to the interface ;)
@ReedCopsey ok fair enough, my assumption was that he just didn't know ;)
2

In your example code, there is no behavior on Animal which is polymorphic - that is, the same message to a reference to the base class results in different concrete behaviors being executed.

Comments

2

You could do it via a interface, which is almost the same thing as your Animal.MakeNoise(), but a little different.

public class Animal
{
}

public interface IAnimalNoises
{
    void MakeNoise();
}

public class Dog : Animal, IAnimalNoises
{
     IAnimalNoises.MakeNoise()
     {
         Bark();
     }

     public void Bark()
     {
     }
}

public class Cat : Animal, IAnimalNoises
{
     IAnimalNoises.MakeNoise()
     {
         Meow();
     }

     public void Meow()
     {
     }
}

public class PatternIamLookingFor
{
    public static void DoSomething(IAnimalNoises animal)
    {
        animal.MakeNoise();
    }
}

Animal cat = new Cat();
Animal dog = new Dog();
PatternIamLookingFor.DoSomething(cat); // -> Call Meow
PatternIamLookingFor.DoSomething(dog); // -> Call Bark

Cat cat2 = new Cat();
cat2.MakeNoise(); //Compiler error as it is not visible unless cast as a IAnimalNoises

If this may be your best option if you are working with legacy code that you can not change, however if you have the option I would highly recommend refactoring your code and just have MakeNoise() called in each of the child classes and have the base class (or interface) define it.

Comments

0

It would be more extensible if you created an interface Called IActions that contain a void MakeNoise() then Implement the Interface on the different animal types.

Override the Way each animal uses the Method. Then just call the method... Example

public class Dog : Animal, IActions //Just import the Interface here
{

//Interface for Makenoise

 public void MakeNoise()
 {
    //Its implementation... Make this different for each animal
 }

}

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.