4

Let's say i have two classes:

class Batman
{
    public void Robin(){...}
    public void Jump(){...}
}

class Superman
{
    public void Kryptonie(){...}
    public void Jump(){...}
}

Now, I have an instance of those classes:

public object Crossover()
{
     var batman = new Batman();
     var superman = new Superman();

     return superman;
}

I do not know instance of which class the Crossover will return, it could be Batman or Superman.

var someVariableName = Crossover(); //I don't know if this contains an instance of Superman or Batman;

//I do know that no matter which class instance is returned, it will always contain a function named Jump which i want to trigger:
someVariableName.Jump();

Now i know i could do something like:

if (someVariableName.GetType() == typeof(Superman)) 
{
    ((Superman) someVariableName).Jump()
}

But is there a way to trigger the Jump function without having to manually check for each type with if..else.., when i know that the instance of the class saved in that variable will always contain a Jump function?

Fred
  • 371
  • 1
  • 5
  • 12
  • as `Crossover` return `object`, this code `var someVariableName = Crossover(); someVariableName.Jump();` just will not compile. It's better to create `interface IJumpingEntity { void Jump()}`, make `Batman` and `Superman` implementing this interface and return object of interface type from `Crossover` – Andrey Korneyev Oct 03 '14 at 13:21
  • What if you had a base class that Batman and Superman both inherited from, put the Jump method in that class, and then had Crossover return an object of the base class type? – Sean Cogan Oct 03 '14 at 13:22
  • 7
    Dear 15K+ rep answerers, are you sure this question is unique? Shouldn't you spent a few seconds finding a reference question instead of answering it? – CodeCaster Oct 03 '14 at 13:25
  • 6
    @CodeCaster This one has super heros though. – asawyer Oct 03 '14 at 13:29
  • 2
    @CodeCaster, [yeah like you do that all the time](http://stackoverflow.com/a/13970279/2711965). – user2711965 Oct 03 '14 at 13:32
  • 3
    @user2711965 that was two years ago. People learn. You're right though, that one should be closed as duplicate of [How do I Convert a string to an enum in C#?](http://stackoverflow.com/questions/16100/how-do-i-convert-a-string-to-an-enum-in-c). – CodeCaster Oct 03 '14 at 13:33
  • 1
    @CodeCaster: You are right. But there is no fun in closing a question. Answering is though... – Patrick Hofman Oct 03 '14 at 13:37
  • 1
    @Patrick thanks for editing and closing that one! :) Keeping the site clean. As more and more questions already are answered, I get more fun from finding duplicates than from typing answers that are already there. :) – CodeCaster Oct 03 '14 at 13:38
  • 1
    @CodeCaster: True. Getting off-topic but my closing-super powers are quite fun indeed ;) – Patrick Hofman Oct 03 '14 at 13:39

3 Answers3

14

Use an interface:

interface ISuperHero
{
    void Jump();
}

class Batman : ISuperHero
{
    public void Robin(){...}
    public void Jump(){...}
}

class Superman : ISuperHero
{
    public void Kryptonie(){...}
    public void Jump(){...}
}

Then return the interface from your method:

public ISuperHero Crossover()
John Koerner
  • 37,428
  • 8
  • 84
  • 134
3

You could create a base class defining the method (or an interface, if it is just about the method definition). You can override the implementation in the deriving classes then.

abstract class ActionFigure
{
    public abstract void Jump(); // just define it has a Jump method, but implement it in the deriving class

    public void SomethingGeneral()
    {
        // no need for an override, just implement it here
    }
}

class Batman : ActionFigure
{
    public void Robin(){...}
    public override void Jump(){...}
}

class Superman : ActionFigure
{
    public void Kryptonie(){...}
    public override void Jump(){...}
}
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
3

This is where interfaces become useful. Consider this interface:

public interface ISuperhero
{
    void Jump();
}

And these implementations:

class Batman : ISuperhero
{
    public void Robin(){...}
    public void Jump(){...}
}

class Superman : ISuperhero
{
    public void Kryptonie(){...}
    public void Jump(){...}
}

They're individual implementations, but they share a common polymorphic interface. Your function can then return that interface:

public ISuperhero Crossover()
{
     var batman = new Batman();
     var superman = new Superman();

     return superman;
}

Since that interface has a Jump() method, it can be called directly:

var someVariableName = Crossover();
someVariableName.Jump();
David
  • 208,112
  • 36
  • 198
  • 279