Dependency injection results with unnecessary implementation - c#

I am creating an Animal class which implements IAnimal interface. Then, both Cats and Dogs classes implement IAnimal interface. Currently I keep only 3 simple methods inside IAnimal for short demonstration. The main class Animals is constructed by using Dependency Injection (DI).
When IAnimal has more methods, for example: Cats class only implements SomethingOnlyCatsDo method, Dogs class implements SomethingOnlyDogsDo method, then there will be more unnecessary implementations inside each of those classes (like Cats().CatchDisk() or Dogs().CatchMouse() in current example).
My question is, is there any way which can help me keep using DI but avoid this growing of unnecessary implementations?
public interface IAnimal
{
void Sound();
void CatchMouse();
void CatchDisk();
// What if there are more methods here
//string GetOwnerName();
//void SomethingOnlyCatsDo();
//void SomethingOnlyDogsDo();
}
public class Cats : IAnimal
{
public void Sound()
{
Console.WriteLine("Meow meow");
}
public void CatchMouse()
{
Console.WriteLine("Catching mouse");
}
public void CatchDisk()
{
throw new NotImplementedException();
}
}
public class Dogs : IAnimal
{
public void Sound()
{
Console.WriteLine("Woof woof");
}
public void CatchDisk()
{
Console.WriteLine("Catching disk");
}
public void CatchMouse()
{
throw new NotImplementedException();
}
}
// Main class
public class Animals
{
private readonly IAnimal _animal;
public Animals(IAnimal animal)
{
_animal = animal;
}
public void Sound()
{
_animal.Sound();
}
public void CatchADisk()
{
_animal.CatchDisk();
}
public void CatchAMouse()
{
_animal.CatchMouse();
}
}

If following SOLID principles, and especially the I (Interface Segregation, https://en.wikipedia.org/wiki/Interface_segregation_principle), IAnimal should not have CatchDisk or CatchMouse methods. Instead you should have IAnimal with the Sound() method, and separate interfaces ICatchesMouse and ICatchesDisk. This way no Animal has to implement unnecessary methods.

You can use Interface Segregation Principle.
The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.
Your IAnimal interface will only have Sound(), then you make a new interface called ICat that inherits from IAnimal and this interface will have CatchMouse(). Your class Cats will inherit from ICat.
Here's a practical example.

Related

Creating an object with the interface name vs class name in C# [duplicate]

I have seen an Interface instance being generated from a class many times. Why do we use interface this way? An interface instance is created only itself with the help of the derived class and we can access only these interface members through this instance. How does this give an advantage? I'm so confused.
interface IPrint
{
void Print();
}
class Sample : IPrint
{
public void Print()
{
Console.WriteLine("Print...");
}
public void Sample()
{
Console.WriteLine("Sample...");
}
}
class Program
{
static void Main(string[] args)
{
IPrint print = new Sample();
print.Print();
}
}
Interfaces define that a class MUST be able to do something. This means that you know the object being worked on will do what you want to be able to do. It allows you greater freedom and is one of the advantages of OOP. This is a deep topic but a very basic example would be this:
public interface IAnimal
{
string Speak();
}
public class Dog : IAnimal
{
public string Speak()
{
return "Woof, woof";
}
}
public class Cat : IAnimal
{
public string Speak()
{
return "Meow";
}
}
public class Parrot : IAnimal
{
public string Speak()
{
return "Sqwark!";
}
}
Then you could use any animal you like!
class Program
{
static void Main(string[] args)
{
// Writes Woof, Woof
IAnimal animal = new Dog();
Console.WriteLine(animal.Speak());
// Now writes Meow
animal = new Cat();
Console.WriteLine(animal.Speak());
// Now writes Sqwark etc
animal = new Parrot();
Console.WriteLine(animal.Speak());
}
}
This also allows you to then get into things like Inversion Of Control where you would take an item in like this and you could pass a dog, cat or parrot and the method would always work, not knowing or caring which animal it was:
public void ShoutLoud(IAnimal animal)
{
MessageBox.Show("Shout " + animal.Speak());
}
This then makes ShoutLoud unit testable because you could use a mock object rather than a real animal. It basically makes your code flexible and dynamic rather than rigid and tightly coupled.
Also, expanding on Matthew's question. In C# you can only inherit from one base class but you can have multiple interfaces. So, you could have:
public class Dog : IAnimal, IMammal, ICarnivor
This allows you to have small interfaces (recommended) that then allow you to build up so giving maximum control over what an item can / must do.
Using an interface this way gives you the ability to create methods that use standard template of the interface. So here you might have many classes of printer that all inherit from IPrinter
class SamsungPrinter : IPrinter
{
// Stuff and interface members.
}
class SonyPrinter : IPrinter
{
// Stuff and interface members.
}
interface IPrinter
{
void Print();
}
So for each type SamsungPrinter, SonyPrinter, etc. you can pre-process using something like
public static void PreProcessAndPrint(IPrinter printer)
{
// Do pre-processing or something.
printer.Print();
}
You know from inheriting from IPrinter and using that type in the method parameters that you can always safely use the Print method on what ever object is passed.
Of course there are many other uses for using interfaces. One example of their use is in design patterns, in particular the Factory and Strategy patterns. The description of which and examples can be found here.
I hope this helps.
But how does this differ from, for example, using a base class with virtual methods?
You are all in the assumption that one programmer or one program writes the interface and the classes, but this doesn't always have to be this way.
Maybe you have a complete finished program that works with animals and you have this worked out using:
public abstract class Animal { public abstract string Speak(); }
And then some day you download some awesome DLL from nuget that shows pictures for animals. The class library contains a contract - interface - 'IAnimal':
namespace AwesomeAnimalLibrary
{
public interface IAnimal
{
string AnimalName;
}
}
The class library also maybe contains :
namespace AwesomeAnimalLibrary
{
public class AnimalPhotos
{
[Byte] GetPhotos(IAnimal animal);
}
}
What could you do now ? Your bas class Animal can implement the AwesomeAnimalLibrary IAnimal interface and that's it.
Don't assume that other people will use you abstract base classes but work together using interface contracts.
Interface can not have instance because interface implements only signatures of properties or methods. Interface is just a pointer to an instance of some class:
interface IExample
{
// method signature
void MyMethod();
}
public class MyClass : IExample
{
// method implementation
public void MyMethod()
{
ConsoleWriteline("This is my method");
}
}
// interface pointing to instance of class
IExample ie = new MyClass();
ie.MyMethod();

Trying to program to abstractions in C# but neither interfaces nor classes really work

I've been trying to apply SOLID principles more consciously on my current project. Using interfaces to create the abstraction and allowing classes that are handling the dependency injection to provide the concretions has really helped with decoupling some of the code and (hopefully!) making it more maintainable in the long run.
However, here and there I'm hitting a bit of a wall where it seems neither interfaces nor abstract classes work for the reason that there are functions for which I want an implementation defined.
This means:
Interfaces will not work since I can't define an implementation and obviously don't want to repeat the code in all implementing classes
Abstract classes will not work because I cannot derive from multiple classes
Some super simple code to illustrate the problem:
public abstract class Vehicle
{
public void MoveForward()
{
// Some code here
// This implementation is always the same
}
public abstract void PerformUniqueAbility(); // This is for the derived class to implement
}
public abstract class RadioSignalBroadcaster
{
public void StartBroadcast()
{
// Some code here
// This implementation is always the same
}
public abstract void PerformUniqueBroadcastingAbility(); // This is for the derived class to implement
}
Now of course what I'd like to do is this:
public class MyNewClass: Vehicle, RadioSignalBroadcaster
{
// Class that contains the implementations for both MoveForward() AND StartBroadcast() but also allows me to define
// bodys for the abstract methods
public override void PerformUniqueAbility()
{
// class specific code here
}
public override void PerformUniqueBroadcastingAbility()
{
// class specific code here
}
}
Of course I cannot do this because of the error:
Error CS1721 Class 'MyNewClass' cannot have multiple base classes: 'Vehicle' and 'RadioSignalBroadcaster'
What's the best way to approach these scenarios?
You could use interfaces with default implementations which were introduced in C# 8. Then you could derive from these interfaces.
Here's an example of how you could you provide default implementations for the MoveForward() and StartBroadcast() methods:
public interface IVehicle
{
void MoveForward()
{
// your code
}
void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
void StartBroadcast()
{
// your code
}
void PerformUniqueBroadcastingAbility();
}
You can't inherit more than 1 class but you can inherit more than one interface. Is this what you are looking for?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
internal class Program
{
static void Main(string[] args)
{
IVehicle vehicle = new Vehicle();
IRadioBroadcaster broadcaster = new RadioBroadcaster();
vehicle.MoveForward();
vehicle.PerformUniqueAbility();
broadcaster.StartBroadcast();
broadcaster.PerformUniqueAbility();
}
}
public interface IUniqueAbillity
{
void PerformUniqueAbility();
}
public interface IVehicle: IUniqueAbillity
{
void MoveForward();
}
public interface IRadioBroadcaster : IUniqueAbillity
{
void StartBroadcast();
}
public abstract class RealWorldObject : IVehicle, IRadioBroadcaster
{
public void MoveForward()
{
// Move forward
}
public abstract void PerformUniqueAbility();
public void StartBroadcast()
{
// Start broadcast
}
}
public class Vehicle : RealWorldObject, IVehicle
{
public override void PerformUniqueAbility()
{
// Do something
}
}
public class RadioBroadcaster : RealWorldObject, IRadioBroadcaster
{
public override void PerformUniqueAbility()
{
// Do something
}
}
}
C# classes can only inherit from one base class, but can inherit from any number of interfaces.
If your goal is to have multiple base classes being inherited to MyNewClass, you could change one of your abstract classes to inherit from the other, for example:
public abstract class RadioSignalBroadcast : Vehicle
{
// Implementation goes here
}
public class MyNewClass : RadioSignalBroacast
{
// Implementation goes here
}
However, as you can see from this approach, it violates Single Responsibility Principle as now RadioSignalBroadcast (and now MyNewClass) has more than one reason to change (if there's a change to Vehicle or RadioSignalBroadcast logic). Any change that happens to any of the base classes will propagate to all other classes which inherit from those base classes, which may or may not be what you're after.
What's the best way to approach these scenarios?
That entirely depends on the design of your application. Questions to ask yourself:
Do you require Vehicle and RadioSignalBroadcast to be abstract classes, or can it easily be an interface? By the looks of your implementation, you have a couple of methods which you want to share to your derived classes so I understand you wanting to keep them as base classes, but it's something to keep in mind. Also check out if the implementation of MoveForward and StartBroadcast can have a default interface implementation.
Does MyNewClass need to implement both base classes/interfaces? Couldn't two separate classes work out better? Separating out classes like this helps to focus each of the classes to have one single responsibility.
If MyNewClass is not truly a Vehicle or a RadioSignalBroadcast (as per the previous point), can this object be composed by a combination of either of the two, for example:
public class MyNewClass : Vehicle
{
private readonly RadioSignalBroadcast radio;
public MyNewClass(RadioSignalBroadcast radio)
{
this.radio = radio;
}
public void DoStuff()
{
// Do Stuff
this.radio.PerformUniqueBroadcastingAbility();
}
// Implementation goes here
}
Let me know if you want example or more points to point out.
I think Jonas gave you the best answer that you can use default interface implementations. However I keep my post, because it gives information, how to achieve same effect, using technology without this language feature.
public abstract class Example : IExample
{
private readonly IVehicle vehicle;
private readonly IRadioSignalBroadcaster;
public Example(IVehicle vehicle, IRadioSignalBroadcaster radioSignalBroadcaster)
{
this.vehicle = vehicle;
this.radioSignalBroadcaster = radioSignalBroadcaster;
}
public void MoveForward() => vehicle.MoveForward();
public void StartBroadcast() => radioSignalBroadcaster.StartBroadcast();
public void PerformUniqueAbility() => vehicle.PerformUniqueAbility();
public void PerformUniqueBroadcastingAbility() => radioSignalBroadcaster.PerformUniqueBroadcastingAbility();
}
public interface IExample : IVehicle, IRadioSignalBroadcaster
{
}
public interface IVehicle
{
void MoveForward();
void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
void StartBroadcast();
void PerformUniqueBroadcastingAbility();
}
public abstract class Vehicle : IVehicle
{
public void MoveForward()
{
// ...
}
public abstract void PerformUniqueAbility();
}
public interface ICustomVehicle : IVehicle
{
}
public class CustomVehicle : Vehicle, ICustomVehicle
{
public void PerformUniqueAbility()
{
// ...
}
}
public abstract class RadioSignalBroadcaster : IRadioSignalBroadcaster
{
public void StartBroadcast()
{
// ...
}
public abstract void PerformUniqueBroadcastingAbility();
}
public interface ICustomRadioSignalBroadcaster : IRadioSignalBroadcaster
{
}
public class CustomRadioSignalBroadcaster : RadioSignalBroadcaster, ICustomRadioSignalBroadcaster
{
public void PerformUniqueBroadcastingAbility()
{
// ...
}
}
You will create another classes like that:
public class CustomExample : Example, ICustomExample
{
public CustomExample(ICustomVehicle customVehicle, ICustomRadioSignalBroadcaster customRadioSignalBroadcaster) : base(customVehicle, customRadioSignalBroadcaster)
{
}
}
public interface ICustomExample : IExample
{
}

Non-Interface methods [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have been reading up on programing to interfaces rather than implementation. One area I am not properly understanding is how to deal with non-interface methods. For example an interface IAnimal and a Cat class that implements it. My examples are in C# but I think it should also apply to other languages.
public interface IAnimal
{
void Eat();
}
public class Cat : IAnimal
{
public Cat()
public void Eat()
{
//Do something
}
public string Meow()
{
return "meow";
}
}
From what I've read it seems like I should be trying to work with the interface rather than the cat implementation such as,
Main()
{
IAnimal cat = new Cat();
}
But this leaves me without access to my meow method as it is not a part of the IAnimal interface. Should I be creating another interface ICat which implements IAnimals and have Cat implement it? And does this mean that all methods should be an implementation from an interface or abstract class? Or am I doing something else here wrong.
Thanks for your help.
What you would do is you is have another interface that represent's speaking animals and either inherit from IAnimal or add it as a 2nd interface. Classes that have animals that speak implement the 2nd interface.
with a inherited interface.
public interface IAnimal
{
void Eat();
}
public interface ISpeakingAnimal : IAnimal
{
string Speak();
}
public class Cat : ISpeakingAnimal
{
public Cat()
public void Eat()
{
//Do something
}
public string Speak()
{
return "meow";
}
}
public class Fish : IAnimal
{
public Fish()
public void Eat()
{
//Do something
}
}
With a 2nd decorator interface
public interface IAnimal
{
void Eat();
}
public interface ISpeakable
{
string Speak();
}
public class Cat : IAnimal, ISpeakable
{
public Cat()
public void Eat()
{
//Do something
}
public string Speak()
{
return "meow";
}
}
public class Fish : IAnimal
{
public Fish()
public void Eat()
{
//Do something
}
}
If you need the method not be Speak() but instead be Meow() you can use explicit interface implementations to expose the Speak() method only though that interface.
public class Cat : ISpeakingAnimal
{
public Cat()
public void Eat()
{
//Do something
}
string ISpeakingAnimal.Speak()
{
return Meow();
}
public string Meow()
{
return "meow";
}
}
The point of an interface is to define behavior common to classes that implement that interface. You are correct in noting that defining cat like so:
IAnimal cat = new Cat();
leaves you unable to access methods in the Cat class that are not in IAnimal. So why is it encouraged to implement things in this way?
The answer is simple: it makes it very easy to change the code later on. For example, if we have a Dog class that implements IAnimal, like so:
public class Dog : IAnimal
{
// some methods
}
then we can very easily replace our Cat class with the Dog class, without having to change any other code. In other words, we can replace:
IAnimal cat = new Cat();
with
IAnimal dog = new Dog();
without having to change any other code in the entire program (besides the variable names). This is because defining Cat and Dog with respect to IAnimal forces them to only use methods found within IAnimal, though they may be implemented differently in Cat and Dog.
Of course, if you want to use something specific only to Cat or Dog, you will have to define the class explicitly, as mentioned by #Erick in his answer, like so:
Cat cat = new Cat();
In general, you should try to define as many common behaviors in the interface as possible, only explicitly casting to a certain class like Cat or Dog when absolutely necessary. This makes your code a lot more versatile and changeable.
If you need to access the method it would be necessary to make an explicit cast.
In this case it would be more interesting to leave your Meow() method more generic for other possible classes that could implement it:
public interface IAnimal
{
void Eat();
void Speak();
}
public class Cat : IAnimal
{
public void Eat() { }
public string Speak()
{
return "meow";
}
}
public class Dog : IAnimal
{
public void Eat() { }
public string Speak()
{
return "au";
}
}
My two cents on this topic is that it's true that you need to depend on abstractions (i.e. interfaces) rather than implementations.
BTW, doesn't this going too far? There's no need to define an interface for any class within your object model. Usually you define interfaces if you need to accept certain objects fulfilling a given contract.
For example, I wouldn't define IAnimal or ICat interfaces. Probably I would define an abstract class Animal and just a concrete class Cat.
If for some reason I need to accept living beings in some API that could eat I would define an interface like this:
public interface IFeedable
{
void Feed(Food food);
}
and if a living being can talk:
public interface ITalkative
{
void Talk(Food food);
}
Unless there's no feature/property/behavior that could be exclusive to animals, I would leave these interfaces as is.
public abstract class Animal : ITalkative, IFeedable
{
public Animal(AudioPlayer audioPlayer)
{
AudioPlayer = audioPlayer;
}
private AudioPlayer AudioPlayer { get; }
public abstract void Feed(Food food);
public void Talk()
{
// Probably you would want to load an animal sound library
// here, and later pass the audio player with the sound library
// already loaded
OnTalk(AudioPlayer.LoadLibrary("animals"));
}
protected abstract void OnTalk(AudioLibrary audioLibrary);
}
public sealed class Cat : Animal
{
public Cat(AudioPlayer audioPlayer) : base(audioPlayer)
{
}
public override void Feed(Food food)
{
if(food is Vegetable)
{
throw new NotSupportedException("MeeEEEEooW (=O ò.ó)=O!!");
}
else if(food is Meat)
{
// Proceed to eat this meat!
}
}
protected override void OnTalk(AudioLibrary audioLibrary)
{
audioLibrary.Play("sweet-cat");
}
}
And if somewhere you need to make an object to talk:
ITalkative talkative = some as ITalkative;
if(talkative != null)
{
talkative.Talk();
}
Or if you need to feed the object:
IFeedable feedable = some as IFeedable;
if(feedable != null)
{
feedable.Feed(new Vegetable());
}
As you can see, you don't define interfaces for everything, but just for those things that you need to handle inside some API and you don't care who can do some actions and/or own some data, but you just care about the object can do or exposes certain behaviors and data respectively.

How to to implementing only one methods from abstract class out of two abstract methods in C#?

In an Abstract class there are two abstract methods Method1() and Method2(),
but I like to inherit only one Method1() in derived Class, how to handle the situation?
public abstract class BaseClass
{
public abstract void Method1();
public abstract void Method2();
}
Really you can't... If you have to (and I would really question the reasons) some options are:
If you do not have any control over the abstract classes involved, and must use this specific abstract class, then, only way is to make the implementation in derived class throw a NotImplementedException.
public MyDerivedClass: BaseClass
{
public override void Method1()
{
// implementation of Method1
}
public override void Method2()
{ throw new NotImplementedException(); }
}
... or create another abstract base class called, say OnlyDOMethod1
public abstract class OnlyDoMethod1
{ public abstract void Method1(); }
then, modify Baseclass so it inherits from OnlyDoMethod1
public abstract class BaseClass: OnlyDoMethod1
{ public abstract void Method2(); }
and use OnlyDoMethod1 anywhere you only want Method1
public MyDerivedClass: OnlyDoMethod1
{
public override void Method1()
{
// implementation of Method1
}
}
It sounds like what you're looking for is interfaces. Something like this:
public interface ICanDoMethod1
{
void Method1();
}
public interface ICanDoMethod2
{
void Method2();
}
Then in your classes you can selectively implement them:
public class JustMethod1 : ICanDoMethod1
{
// implement Method1 here
}
public class Both : ICanDoMethod1, ICanDoMethod2
{
// implement both here
}
// etc.
Essentially, any given class either can or can not be polymorphically interpreted as any given type. If you want to be only part of a type, then what you really have is two types. C# is single-inheritance, so to implement multiple types you would use interfaces.
Conversely, you could also chain your inheritance. Something like this:
public abstract class Base1
{
public abstract void Method1();
}
public abstract class BaseBoth : Base1
{
public abstract void Method2();
}
public class JustOne : Base1
{
// only implement Method1 here
}
public class Both : BaseBoth
{
// implement both here
}
That'll work if the options stack, that is if you don't want to be able to pick and choose and either want "1" or "1 and 2" (but not just "2").
As a last resort, you can "selectively implement" methods by explicitly not implementing the others. It would looks something like:
public class JustOne : BaseClass
{
public override void Method1()
{
// implement
}
public override void Method2()
{
throw new NotImplementedException();
}
}
But this would be something of an anti-pattern, where your objects would advertise functionality that they intentionally do not support. This would mean that the type BaseClass should be considered very unstable/unreliable, because there's no way for anything consuming that type to know how it should actually behave.
Ultimately, it sounds like you've painted yourself into a corner with your types and you need to back up a little and re-think them. Liskov Substitution shouldn't be taken so lightly.
This is basic example of violation of one of SOLID principles Interface segregation principle
A client should never be forced to implement an interface that it
doesn’t use or clients shouldn’t be forced to depend on methods they
do not use
If you have abstraction where you need only some of method you need to split them in separated abstractions.
.NET do not support multi-inheritance from classes, nut have nice workaround for this problem -> interfaces.
If you care about your code, then you have only one option - split abstract class into two separated classes which have only one method.
If you work only with abstraction then interfaces is better approach, because you can implement multiply interfaces in one class.
public interface IMethodOne
{
void Method1();
}
public interface IMethodTwo
{
void Method2();
}
Then you can implement that both interfaces in the class which needs both methods. And use only one interface in the class with one method needs.
public abstract class BaseClass : IMethodOne, IMethodTwo
{
public abstract void Method1();
public abstract void Method2();
}
And class with one method
public abstract class BaseClassOneMethod : IMethodOne
{
public abstract void Method1();
}

I have a base class. How do I call the right method for the right derived class?

Obviously trying to simplify the problem here. I have a base class and a number of derived classes:
public class Mammal { }
public class Cat : Mammal { }
public class Dog : Mammal { }
And a utility class:
public static class AnotherClass
{
public static void GiveFood(Cat cat) {}
public static void GiveFood(Dog dog) {}
}
Somewhere else is a method, Feed, which takes a Mammal, and from within there i want to call the right overload on AnotherClass:
public void Feed(Mammal mammal) {
// if mammal is a cat, call the AnotherClass.GiveFood overload for cat,
// if it's a dog, call the AnotherClass.GiveFood for dog, etc.
}
One way to do that would be to do something like:
public void Feed(Mammal mammal) {
if (mammal is dog)
AnotherClass.GiveFood((Dog)mammal);
if (mammal is Cat)
AnotherClass.GiveFood((Cat)mammal);
}
...but I actually have a huge number of animals derived from Mammal. Is there a nicer way to do what I want to do in Feed()? Is there any way I can avoid having Feed() end up being a huge ugly method filled with these "if x is y then call z"-statements?
I don't usually like using dynamic, but this is one of the cases where I think it's appropriate:
public void Feed(Mammal mammal) {
Anotherclass.GiveFood((dynamic)mammal);
}
That will resolve the correct overload at runtime, without knowing the type in advance.
Strictly speaking, this probably isn't going to be the fastest method, but as you point out, the alternatives can be a real pain to maintain, and/or hard to read. In this case, dynamic dispatch is elegant and will automatically incorporate any overloads you add in the future.
As Chris Sinclair points out, you could also add a catchall method to detect any invalid calls and provide a friendlier exception than the runtime error you'd receive if no matching GiveFood() overload could be found:
public static class AnotherClass
{
public static void GiveFood(Cat cat) {}
public static void GiveFood(Dog dog) {}
public static void GiveFood(Mammal mammal)
{
throw new AnimalNotRecognizedException("I don't know how to feed a " + mammal.GetType().Name + ".");
}
}
I think it's the animal's responsibility to process food, not the feeder. Otherwise you'll run into the problem you now have:
public void Feed(Mammal mammal) {
if (mammal is Duck)
{
((Duck)mammal).PryOpenBeak();
((Duck)mammal).InsertFeedingTube();
((Duck)mammal).PourDownFood();
}
}
And so on, although ducks aren't mammals.
Anyway, your Mammal class should have an abstract method Feed(Food food), and the animal itself will have to figure out how to process the food. This way when later adding a new mammal, you won't have to update the feeder with the feeding logic for this new mammal.
#Chris's comment: then the animal could implement the proper IFoodXEater interface that contains a Feed(IFoodX) method, and then the feeder can look that up, although then you're back at square one:
if (mammal is IFishEater)
{
((IFishEater)mammal).Feed(new Fish());
}
My Recommendation:
Step 1: Create an interface IMammal
<!-- language: c# -->
public interface IMammal
{
void Feed();
}
Step 2: (Optional) Implement a Base class BaseMammal
public class BaseMammal : IMammal
{
public void Feed()
{
Trace.Write("basic mammal feeding");
//a basic implementation of feeding, common to all or most mammals
}
}
Step 3: Implement your inherited classes
public class Cat : BaseMammal
{
public void Feed()
{
Trace.Write("cat feeding");
BePicky();//some custom cat like functionality
base.Feed(); //and afterwards its still just a mammal after all
}
}
public class Gruffalo : BaseMammal
{
public void Feed()
{
Trace.Write("Gruffalo feeding");
WeirdWayOfEating();//the base implementation is not appropriate
}
}
Step 4: Use! (random example included)
List<IMammal> pets = new List<IMammal>()
{
new Cat(catValues),
new Gruffalo(gruffaloValues)
};
foreach(var pet in pets)
{
pet.Feed();
}
Each animal will be fed by their own implementation. Lo and behold - your complex code is now simple. I would also recommend that you read "Head First Design Patterns", which explains this and many other concepts. http://www.amazon.co.uk/Head-First-Design-Patterns-Freeman/dp/0596007124
If you don't mind the effort of creating a type map, you can fake double dispatch like so:
[EDIT] This new, improved version handles subclasses better. If you have a class derived from another mammal class (such as Pug derived from Dog in the example below) then you don't need to explicitly add a feeder for class Pug - it will automatically call the feeder for its base class, Dog.
But you can have a specific feeder for a derived class if you want, as demonstrated by the Manx class below.
Using dynamic is much much easier though! I just wanted to show how it could look if you weren't using dynamic.
using System;
using System.Collections.Generic;
namespace Demo
{
public class Mammal {}
public class Cat: Mammal {}
public class Pig: Mammal {}
public class Dog: Mammal {}
public class Pug: Dog {}
public class Manx: Cat {}
public static class Feeder
{
static readonly Dictionary<Type, Action<Mammal>> map = createMap();
static Dictionary<Type, Action<Mammal>> createMap()
{
return new Dictionary<Type, Action<Mammal>>
{
{typeof(Cat), mammal => GiveFood((Cat) mammal)},
{typeof(Dog), mammal => GiveFood((Dog) mammal)},
{typeof(Manx), mammal => GiveFood((Manx) mammal)}
};
}
public static void GiveFood(Mammal mammal)
{
for (
var currentType = mammal.GetType();
typeof(Mammal).IsAssignableFrom(currentType);
currentType = currentType.BaseType)
{
if (map.ContainsKey(currentType))
{
map[currentType](mammal);
return;
}
}
DefaultGiveFood(mammal);
}
public static void DefaultGiveFood(Mammal mammal)
{
Console.WriteLine("Feeding an unknown mammal.");
}
public static void GiveFood(Cat cat)
{
Console.WriteLine("Feeding the cat.");
}
public static void GiveFood(Manx cat)
{
Console.WriteLine("Feeding the Manx cat.");
}
public static void GiveFood(Dog dog)
{
Console.WriteLine("Feeding the dog.");
}
}
class Program
{
void test()
{
feed(new Cat());
feed(new Manx());
feed(new Dog());
feed(new Pug());
feed(new Pig());
feed(new Mammal());
}
void feed(Mammal mammal)
{
Feeder.GiveFood(mammal);
}
static void Main()
{
new Program().test();
}
}
}
If more than one animal shares the feeding behavior, I'll suggest to use the strategy pattern to encapsulate the feeding behavior in an interface and concrete implement each behavior for each group of animals
you will be using composition instead of inheritance
check the head first design patterns for this one I think it will be a good implementation in your case

Categories

Resources