In C# I know there is a way of switching method calls based on the concrete type of an abstract parameter at run time.
So in the example below the entire Wash(Animal) method is not needed and C# will know which Cat/Dog method to call based on the concrete type of Animal at run time. There's syntax to do this, I've done this before but I can't for the life of me remember what it is.
public void Wash(Animal animal)
{
switch (animal)
{
case Cat cat:
Wash(cat);
break;
case Dog dog:
Wash(dog);
break;
}
}
public void Wash(Cat cat)
{
}
public void Wash(Dog dog)
{
}
Could be done using double dispatch...
abstract class Animal
{
public abstract void TakeBath(AnimalWasher washer);
}
class Cat : Animal
{
public override void TakeBath(AnimalWasher washer)
{
washer.Wash(this);
}
}
class Dog : Animal
{
public override void TakeBath(AnimalWasher washer)
{
washer.Wash(this);
}
}
class AnimalWasher
{
public void Wash(Cat cat)
{
Console.WriteLine("washing a cat");
}
public void Wash(Dog dog)
{
Console.WriteLine("washing a dog");
}
}
class Program
{
static async Task Main(string[] args)
{
AnimalWasher washer = new AnimalWasher();
Animal dog = new Dog();
Animal cat = new Cat();
dog.TakeBath(washer);
cat.TakeBath(washer);
}
Thank you Mr Skeet for scratching my itch. Dynamic binding is exactly what I was trying to remember.
public void PetGroom(Animal animal)
{
Wash(animal as dynamic);
}
public void Wash(Cat cat)
{
}
public void Wash(Dog dog)
{
}
Related
I have an animal manager class that has a list of object that implement the IAnimal interface. It has a method that must get the cats only from that same list. How can I design my code in a better way to achieve this?
Sample code is below (in C#):
public interface IAnimal
{
void doSomeThing();
}
public class Cat : IAnimal
{
public void doSomeThing()
{
Console.WriteLine("Cat");
}
}
public class Dog : IAnimal
{
public void doSomeThing()
{
Console.WriteLine("Dog");
}
}
public class AnimalManager
{
private List<IAnimal> animals = new List<IAnimal>();
private void manageCat()
{
// Get cats from animals list.
}
}
var cats = animals.OfType<Cat>()
Just compare the type:
public class AnimalManager
{
private List<IAnimal> animals = new List<IAnimal>();
private void manageCat()
{
var OnlyCats = animals.Where(animal => animal.GetType() == typeof(cat));
}
}
I do not see any issue with your design. You could of course keep separate lists for each type of animal; however, this is not very elegant and will require more code in most cases.
Keeping all of them in a single list and applying a filter when required allows you to treat all the animals at once.
private void manageCat()
{
foreach (Cat cat in animals.OfType<Cat>()) {
cat.DoCatSpecificThing();
}
}
An alternative design would be to add another method doing very special things like catching mice that would probably only have a non-empty implementation for cats:
public interface IAnimal
{
void DoGeneralThing();
void CatchMouse();
}
Possible implementation:
public class Cat : IAnimal
{
public void DoGeneralThing()
{
Console.WriteLine("Cat");
}
public void CatchMouse()
{
Console.WriteLine("Got you, meow");
}
}
public class Dog : IAnimal
{
public void DoGeneralThing()
{
Console.WriteLine("dog");
}
public void CatchMouse()
{
}
}
Possible use:
private void ManageCatchinggMice()
{
foreach (IAnimal animal in animals)
{
animal.CatchMouse();
}
}
I'm solving this problem with polymorphism. I need to print out verse of the song with 5 animals.The verse is repeated for each animal and the appropriate sound for the animal is used eg cows go “moo”, ducks go “quack” etc. I would like to ask is it possible to have a class only with methods. In addition here is my code.
public class Animal
{
public virtual void PrintSong()
{
}
}
public class Cow : Animal
{
public override void PrintSong()
{
Console.WriteLine("I go \"Mooo\" (I'm a cow, I'm a cow, I'm a cow)");
}
}
public class Pig : Animal
{
public override void PrintSong()
{
Console.WriteLine("I go \"Oink\" (I'm a pig, I'm a pig, I'm a pig)");
}
}
static void Main(string[] args)
{
Animal[] animals = new Animal[2];
animals[0] = new Cow();
animals[1] = new Pig();
foreach (Animal a in animals)
{
a.PrintSong();
}
}
Yes
A class doesnt have to have methods or fields / variables
polymorphism example:
public class animal
{
public void virtual speak()
{
Console.WriteLine("Animals can speak in many ways.");
}
}
public class dog : animal
{
public void override speak()
{
Console.WriteLine("I bark!");
}
}
static void main()
{
animal doggy = new dog();
doggy.speak();
}
output:
I bark!
I keep reading that the correct speak method is called during runtime, but is it not already hard coded and does the compiler not recognize which method it will invoke based on the virtual and override keywords?
Your compiler doesn't necessarily know which implementation will be the underlying type. Take, for example:
class A
{
public virtual void F() { Console.WriteLine("A"); }
}
class B : A
{
public override void F() { Console.WriteLine("B"); }
}
class Program
{
static A GetImpl(int i)
{
switch(i)
{
case 1:
return new A();
case 2:
return new B();
default:
// whatever
}
}
static void Main(string[] args)
{
var i = int.Parse(Console.ReadLine());
A a = GetImpl(i);
a.F();
}
}
How could the compiler possibly know if an A or a B is returned? It cannot, so the task of calling the correct method is delegated to the runtime.
If your code was something like
Animal anAnimal= NoahsArc.getNextAnimal();
anAnimal.speak();
Now you don't actually know what sort of animal you are going to get, so the runtime ensures the correct speak method is called.
I have a method which uses a generic parameter and requires the downcasted form of the instance. For example,
public abstract class Animal {
}
public class Dog : Animal {
}
public class Cat : Animal {
}
public class AnimalHandler {
public virtual void Pet<T>(T animal)
{
}
}
Given a collection of animals.
public List<Animal> Animals { get; set; }
How do I downcast individual animals before calling the Pet method?
I currently having working in this form.
if (animal is Dog) {
_animalHandler.Pet((Dog)animal);
}
if (animal is Cat) {
_animalHandler.Pet((Cat)animal);
}
Ideally, it would be something of this form.
var type = animal.GetType();
_animalHandler.Pet(animal.CastTo(type));
Clarification: I need the instance to be of the downcasted type before it is passed to the method. I need a Dog or Cat specifically to be passed in.
You can accomplish this using the new .NET 4 dynamic keyword:
namespace Rextester
{
public class Program
{
public abstract class Animal {
}
public class Dog : Animal {
}
public class Cat : Animal {
}
public class AnimalHandler {
public virtual void Pet<T>(T animal) {
Console.WriteLine(typeof(T));
}
}
public class Problem {
public List<Animal> Animals { get; set; }
private readonly AnimalHandler _animalHandler;
public Problem(AnimalHandler animalHandler) {
_animalHandler = animalHandler;
Animals = new List<Animal> { new Cat(), new Dog() };
}
public void MakeDecision() {
foreach (var animal in Animals) {
_animalHandler.Pet(animal);
}
}
}
public static void Main(string[] args)
{
List<Animal> animals = new List<Animal>();
animals.Add(new Dog());
animals.Add(new Cat());
var handler = new AnimalHandler();
handler.Pet((dynamic)animals[0]);
handler.Pet((dynamic)animals[1]);
}
}
}
Notice the cast to dynamic in the calls to Pet. Though doing it this way negates the necessity of Pet being generic in the first place.
If, as your clarification says, you "Need a concrete Dog or Cat to be passed in" then your method cannot take a generic Animal.
However, what I suspect you're missing is that the Handler should not need to know what type of animal it has, only how to Handle that Animal. See this expanded example:
public abstract class Animal {
public abstract void Speak();
}
public class Dog : Animal {
public override void Speak(){ Console.WriteLine("WOOF!! You're great."); }
}
public class Cat : Animal {
public override void Speak(){ Console.WriteLine("Meow. Im better than you."); }
}
public class AnimalHandler {
public virtual void Pet<T>(T animal) where T : Animal
{
animal.Speak();
}
}
When executing this with the following code:
List<Animal> animals = new List<Animal>();
animals.Add(new Dog());
animals.Add(new Cat());
var handler = new AnimalHandler();
handler.Pet(animals[0]);
handler.Pet(animals[1]);
Im sure you can imagine the output (If not, Live example: http://rextester.com/UJZRB90548). You see from this, I only have a list of Base Animal, but when it is passed in to the Handler, the correct method is called.
You have a few alternatives. One approach would be to have sub-classes of AnimalHandler per animal type and manually dispatch to the correct one:
public class AnimalHandler
{
public void Pet(Animal animal)
{
if (animal is Cat)
{
this.catHandler.Pet((Cat) animal);
}
else if (animal is Dog)
{
this.dogHandler.Pet((Dog) animal);
}
else
{
throw new ArgumentOutOfRangeException("animal");
}
}
private readonly CatHandler catHandler;
private readonly DogHandler dogHandgler;
}
As an alternative to all the 'if's and 'is's you could add an AnimalType enum property to the Animal class and use a switch statement.
The above approach could be made a bit more generic and extensible by creating an interface to represent a specific animal type handler:
public enum AnimalType
{
Cat,
Dog,
}
public interface ISpecificAnimalHandler
{
AnimalType AnimalType { get; }
void Pet(Animal animal);
}
public class AnimalHandler
{
public AnimalHandler()
{
var handlers = new ISpecificAnimalHandler[] { new CatHandler(), new DogHandler() };
this.handlersByAnimal = handlers.ToDictionary(handler => handler.AnimalType, handler);
// ...
}
public void Pet(Animal animal)
{
ISpecificAnimalHandler handler;
if (!this.handlersByAnimalType.TryGet(animal.AnimalType, out handler))
{
throw new ArgumentOutOfRangeException("Animal of type " + animal.GetType().Name " not supported.");
}
handler.Pet(animal);
}
private IDictionary<AnimalType, ISpecificAnimalHandler> handlerByAnimalType;
}
public class CatHandler : ISpecificAnimalHandler
{
public AnimalType AnimalType
{
get { return AnimalType.Cat;
}
public void Pet(Animal animal)
{
var cat = (Cat) animal;
// do petting, meow
}
}
Another, different, option is to use dynamic dispatch:
public class AnimalHandler
{
public void Pet(Animal animal)
{
PetAnimal((dynamic) animal); // will dispatch to most appropriate method at runtime
}
public void PetAnimal(Cat cat)
{
// do petting, meow
}
public void PetAnimal(Dog dog)
{
// do petting, woof
}
}
I was feeling quite clever as I worked out how to create subclasses in C# for an ASP.NET project, then I found a problem - I didn't know how to create an object of the right subclass based on the results of a SQL query.
Say you have a class called Animal and two subclasses called Zebra and Elephant. You get the idea?
What I want to do is perform a SQL query and if the row returned has row["Type"]="Zebra" then load a Zebra object (or if it's an Elephant then..).
So, in principle, the Animal class would have a static method:
class Animal{
public static Animal Load(DataRow row){
if (row["Type"]=="Zebra"){
return new Zebra();
}
}
class Zebra : Animal{
//some code here
}
Is this at all possible or have I just plain got the idea of subclasses wrong. It should be obvious I'm no OO expert.
Thanks in advance,
Jake
You can implement the method factory pattern.
http://en.wikipedia.org/wiki/Factory_method_pattern
Try this:
public interface IAnimal
{ }
public class Animal : IAnimal
{
public static IAnimal Load(String type)
{
IAnimal animal = null;
switch (type)
{
case "Zebra" :
animal = new Zebra();
break;
case "Elephant" :
animal = new Elephant();
break;
default:
throw new Exception();
}
return animal;
}
}
public class Zebra : Animal
{
public int NrOfStripes { get; set; }
public static Zebra ZebraFactory()
{
return new Zebra();
}
}
public class Elephant : Animal
{
public int LengthOfTrunk { get; set; }
}
And to try it:
class Program
{
static void Main(string[] args)
{
IAnimal zebra = Animal.Load("Zebra");
IAnimal elephant = Animal.Load("Elephant");
}
}
I think it's fine:
public class Animal
{
public static Animal Load(string row)
{
if (row == "Zebra")
{
return new Zebra();
}
else if (row == "Elephant")
{
return new Elephant();
}
return null;
}
}
public class Zebra : Animal
{
public new string ToString()
{
return "Zebra";
}
}
public class Elephant : Animal
{
public new string ToString()
{
return "Elephant";
}
}
static void Main(string[] args)
{
Animal a1 = Animal.Load("Zebra");
System.Console.WriteLine(((Zebra)a1).ToString());
System.Console.WriteLine(((Elephant)a1).ToString()); // Exception
Animal a2 = Animal.Load("Elephant");
System.Console.WriteLine(a2.ToString());
}