Right now I have a kind of dilemma. There is a class structure that is similar to the following one:
public interface IMammal
{
void Eat();
}
public interface IBarking
{
void Bark();
}
There are instances of IBarking and IMammal. Theoretically our animal can be either of them or just one. Cow is as you can see IMammal, and Dog is IMammal and IBarking. In theory we could even have someone who can bark, but isn't a mammal.
public class Mammal : IMammal
{
public void Eat()
{
Console.Write("Om-nom-nom");
}
}
public class Cow : Mammal
{
}
public class Dog : Mammal, IBarking
{
public void Bark()
{
Console.Write("Bark-bark!!!");
}
}
Here is a Farm, where only one animal lives:
public class Farm
{
private readonly IMammal _animal;
public Farm(IMammal animal)
{
_animal = animal;
}
public void Feed()
{
_animal.Eat();
}
public void Guard()
{
var dog = _animal as IBarking;
if (dog != null)
dog.Bark();
}
}
The problem, I can see here, is that we assume that IBarking is always IMammal. What is wrong with this design, how could it be fixed?
Such simplified examples hardly make any sense. You're missing the "problem case" and what you want to do then. Show a class that implements IBarking but not IMammal and what problems arise when you pass it to Farm. Anyway, given the premises:
Interface IMammal exists.
Interface IBarking exists.
A class implementing IBarking does not have to implement IMammal.
Class constructor Farm has to accept IBarking and IMammal.
Current class constructor accepts IMammal.
In this case you either need a new constructor, a new private member and more code to choose between the two, or an overlapping interface. I'd go with the latter: IFarmable.
Then you need:
public interface IMammal : IFarmable
public interface IBarking : IFarmable
public Farm(IFarmable farmable) { ... }
Most likely you have other constraints, like "but I want to call Eat() on the variable passed into the constructor", but then your description ("we assume that IBarking is always IMammal") is incorrect or incomplete and you need to move Eat() to the IFarmable interface.
I'll try to interpret your intention.
You want to have a farm where animals grow up (to later be slaughtered for food).
You might need another animal guarding them (might since you tried the cast).
A better design for that would be:
public class Farm
{
private readonly IMammal[] _animals;
public Farm(IMammal[] animals)
{
_animals = animals;
}
public void Feed()
{
foreach (var animal in _animals)
animal.Eat();
}
public IBarking GuardingAnimal { get; set; }
public void Guard()
{
if (GuardingAnimal != null)
GuardingAnimal .Bark();
}
}
Changes from your design:
I've made it crystal clear that there can be a guarding animal
The guarding animal is optional (as it's assign through a property instead of the constructor).
The reason that I wanted to make that distinction is that most animals are passive (you feed and harvest them) while the guard animal has a specific use case and should therefor not be hidden among the others.
If you want to feed the dog you, you should make that interface inherit IMammal (unless you introduce more functionality in mammal in which case you should extract IFeedable or similar).
Related
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();
I want to avoid using casting base class type to derived class type I can do this successfully If I want to access generic functionality but if I want specialised functionality I cant access this without casting
I have written code to demonstrate what I've already tried.
public abstract class Animal : IAnimal
{
public void Move()
{
}
}
public interface IAnimal
{
void Move();
}
public interface IDog:IAnimal
{
void bark();
}
public class Dog : IDog
{
public void Move()
{
}
public void bark()
{
}
}
static void Main(string[] args)
{
Animal animal = null;
IDog dog = animal as IDog;
dog.bark(); // can access specialized method
IAnimal puppy = new Dog();
puppy.Move(); // can only access generic functions
}
How can I re-design classes to access "bark" method without casting?
Short answer: You cannot and you shouldn't be able.
What you could do instead, is probably implement a MakeNoise() method in IAnimal interface because you'd expect animals in general to make noises.
However, if you insist on keeping Bark() on IDog, you wouldn't expect an IDuck to be able to access it - it should have a Quack() method. Neither will be available from objects downcasted to IAnimal because how can you guess whether it's a Duck or a Dog?
I'll post bit more "real life" example of why you might need inheritance in programming, because example you've provided is sort-of "book example" and thus it is obscure and vague as well.
using System.Collections.Generic;
namespace ConsoleApp1
{
public static class DocumentHandling
{
public static List<IAccountable> Documents;
public static dynamic InternalService { get; set; }
public static dynamic IRS { get; set; }
public static void HandleDocuments()
{
foreach (var document in Documents)
{
document.Account();
}
}
}
public interface IAccountable
{
void Account();
}
public abstract class Document
{
public int DatabaseId { get; set; }
public string Title { get; set; }
}
public abstract class DocumentWithPositions : Document
{
public int[] PositionsIds { get; set; }
}
public class Invoice : DocumentWithPositions, IAccountable
{
public void Account()
{
var positions = DocumentHandling.InternalService.PreparePositions(this.PositionsIds);
DocumentHandling.IRS.RegisterInvoice(positions);
}
}
public class Receipt : DocumentWithPositions, IAccountable
{
public void Account()
{
Invoice invoice = DocumentHandling.InternalService.ConvertToReceipt(this);
invoice.Account();
}
}
}
See how I can stuff both Invoice and Receipt documents in single List (because they're downcasted to IAccountable)? Now I can account them all at once, even though their concrete implementations handle accounting process differently.
Let's takle the Liskov Substitution Principle first and then talk about OOP and inheritance.
First, lets talk about Abstract Data Types. In her paper she uses the concept of objects from types.
An Abstact Data Type (ADT) is a description of a type with all it's operations and behaviors. All clients of an ADT should know what to expect when using it.
Here's an example:
Let's define a Stack as an ADT
Operations: push, pop, topElement, size, isEmpty
Behaviors:
push : always adds an element to the top of the stack!
size : return the number of elements in the stack
pop : removes and element from the top of the stack. error if the stack is empty
topElement : return the top element in the stack. error if the stack is empty
isEmpty : return true is the stack is empty, false otherwise
At this point we desribed what is a Stack in terms of it's operations and how it should behave. We are not talking about clases here nor concrete implementations. This makes is an Abstract Data Type.
Now lets make a type hierarchy. In C# both interfaces and classes are types. They are different as interfaces define only operations, so in a sense they are a contract. They define the operations of an ADT. Usually people do assume that only classes that inherit from one another define a type hierarchy. It's true that classes that inherit from one another are called Superclass or Baseclass and a Subclass, but from the point of view of Types we do have Supertype and Subtype for both interfaces and classes as they both define types.
NOTE: For simplicity i'll skip error checking in the implementations of the methods
// interfaces are types. they define a contract so we can say that
// they define the operations of an ADT
public interface IStack<T> {
T Top();
int Size();
void Push(T element);
void Pop();
bool IsEmpty();
}
// the correct term here for C# whould be 'implements interface' but from
// point of view of ADTs and *Types* ListBasedStack is a *Subtype*
public class ListBasedStack<T> : IStack<T> {
private List<T> mElements;
public int Size() { return mElements.Count; }
public T Top() { mElements(mElements.Count - 1); }
public void Push(T element) { mElements.Add(element); }
public void Pop() { mElements.Remove(mElements.Count - 1); }
public bool IsEmpty() { return mElements.Count > 0; }
}
public class SetBasedStack<T> : IStack<T> {
private Set<T> mElements;
public int Size() { return mElements.Count; }
public T Top() { mElements.Last(); }
public void Push(T element) { mElements.Add(element); }
public void Pop() { mElements.RemoveLast(); }
public bool IsEmpty() { return mElements.Count > 0; }
}
Notice that we have two Subtypes of the same ADT. Now lets consider a test case.
public class Tests {
public void TestListBasedStackPush() {
EnsureUniqueElementsArePushesToAStack(new ListBasedStack<int>());
}
public void TestSetBasedStackPush() {
EnsureUniqueElementsArePushesToAStack(new SetBasedStack<int>());
}
public void EnsureUniqueElementsArePushesToAStack(IStack<int> stack) {
stack.Push(1);
stack.Push(1);
Assert.IsTrue(stack.Size() == 2);
}
}
And the results are:
TestListBasedStackPush: Pass
TestSetBasedStackPush: FAIL!
SetBasedStack violates the rules for push: always adds an element to the top of the stack! as a set can contain only unique elements and the second stack.Push(1) wont add new element to the stack.
This is a violation of LSP.
Now about examples and type hierarchies like IAnimal and Dog. When you are in the right abstaction level a type should behave like it's suposed to. If you do need a Dog, use a Dog. If you do need an IAnimal, use IAnimal.
How do you access Bark if you have IAnimal? You DON'T!!. You are at the wrong level of abstraction. If you do need a Dog, use a Dog. Cast if you have to.
public class Veterenerian {
public void ClipDogNails(IAnimal animal) { } // NO!
public void ClipDogNails(Dog dog) { } // YES!
}
private Veterenerian mOnDutyVeterenerian;
private List<IAnimal> mAnimals;
public ClipAllDogsNails() {
// Yes
foreach(var dog in mAnimals.OffType<Dog>()) {
mOnDutyVeterenerian.ClipDogNails(dog);
}
// NO
foreach(var animal in mAnimals) {
mOnDutyVeterenerian.ClipDogNails(animal);
}
}
Do you need to cast? Sometimes yes. If it better to not do it? Yes, most of the time.
How do you solve the above problem? You can make the Dog clip it's own nails. Are you doing to add method ClipNails to IAnimal and make only animals with nails implement this and leave other animal subclasses leave this method empty? NO! Because it doesn't make sense in the level of abstraction of IAnimal and it also violates LSP. Also if you do this you can call animal.ClipNails() and this will be fine, but if you do have a schedule that says that dogs should clip nails on Friday other animals Monday your stuck again as you can make all animals clip their nails, not only dogs.
Sometimes an object of one Type is to be used by objects from another Type. Some operations doesn't make sense in a type. This example illustates how a Dog cannot clip it's nails. It should be done by a Veterenerial.
Yet we do need to work on the IAnimal level of abstraction. All things in a Veterenerian Clinic are animals. But sometimes some operations need to be performed on specific type of animal, a Dog in this case, so we do need to filter the animals by their Type.
But that's a completely different problem from the above example with Stack.
Here's an example on when casting should not be used and the client code should not case about the concrete implementation:
public abstract class Serializer {
public abstract byte[] Serialize(object o);
}
public class JSONSerializer : Serializer {
public override byte[] Serialize(object o) { ... }
}
public class BinarySerializer : Serializer {
public override byte[] Serialize(object o) { ... }
}
public void DoSomeSerialization(Serializer serializer, Event e) {
EventStore.Store(serializer.Serialize(e));
}
DoSomeSerialization method should not care about the serializer that is passed to it. You can pass any Serializer that adheres to the Serializer spec, it should work. That's the point of having an abstraction with multiple implemenations. DoSomeSerialization works on the level of Serializer. We can define the Serializer as an ADT. All classes that are derive from Serializer should adhere to the specification of the ADT and the system works just fine. No casting here, no need to do casting here as the problem is different.
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.
I am implementing a collection of classes that exhibit the following pattern:
public class Animal {}
public abstract class AnimalToy
{
public AnimalToy(Animal owner)
{
Owner = owner;
}
public Animal Owner { get; private set; }
/* Various methods related to all toys that use the Owner property */
}
public class Dog: Animal
{
public void Bark() {}
}
public class PlasticBone: AnimalToy
{
public PlasticBone(Dog owner) : base(owner) {}
public void Throw()
{
((Dog)Owner).Bark();
}
}
I have a base class AnimalToy with a property that is a reference to another base class Animal.
I now want to implement a Dog and a PlasticBone toy for that Dog class. PlasticBone is a toy that's only valid for dogs, and in fact the constructor restricts the owner of PlasticBone to be of type Dog.
PlasticBone has a method Throw() that is unique to that class, that uses a method on Dog (Bark()) that is unique to the Dog class. Therefore I need to cast the generic property Owner to Dog before I can access it.
This works just fine, but in the project I am working on this situation comes up again and again and leads to quite ugly code where the methods of derived classes are full of downcasts of base class references. Is this normal? Or is there a better overall design that would be cleaner?
Here's one way to fix it:
public abstract class Animal
{
public abstract void MakeNoise();
}
Let dog implement the MakeNoise and you can just call that in your Toy class:
public void Throw()
{
Owner.MakeNoise();
}
You can make AnimalToy class generic, by this you can avoid casting.
public abstract class AnimalToy<TAnimal> where TAnimal : Animal
{
public AnimalToy(TAnimal owner)
{
Owner = owner;
}
public TAnimal Owner { get; private set; }
}
public class PlasticBone: AnimalToy<Dog>
{
public PlasticBone(Dog owner) : base(owner) {}
public void Throw()
{
Owner.Bark();
}
}
Worth noting that ((Dog)Owner) is not upcast, it is called downcast. upcast is over way around.
I'm going to try to elaborate a little on the discussion in the comments and hopefully provide you with a generalised, polymorphic solution. The general idea is functionally equivalent to what Carra was suggesting but, hopefully, this will help you to apply those concepts to the domain of your actual problem.
To work with your abstraction of your problem; suppose you have your abstract base class defined like so:
public abstract class Animal
{
public abstract void Catch();
}
This is a shift in the semantics of the abstract method; you no longer have an abstract Bark method, you simply have a Catch method, the semantics of which define it as, essentially "react to something being thrown." How the Animal reacts is entirely up to the animal.
So, you'd then define Dog like so:
public class Dog : Animal
{
public override void Catch()
{
Bark();
}
public void Bark()
{
// Bark!
}
}
And change your Throw method to:
public void Throw()
{
Owner.Catch();
}
Now, Bark is specific to Dog, while the generic Catch method is universal to all Animals. The Animal class now specifies that its subclasses must implement a method that reacts to items being thrown to it. The fact that the Dog barks is entirely up to the Dog.
This is the essence of polymorphism - it's not up to the toy to determine what the dog does; it's up to the dog. All the toy needs to know is that the dog can catch it.
More generally, though, I don't like to have two classes that extend independent base classes be logically coupled (parallel hierarchies, as Eric points out) unless one of them explicitly instantiates the other, though it's impossible to offer any real advice on that without seeing your actual solution architecture.
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