Passing Derived class as a parameter to a method when the parameter type is base class

C#Inheritance

C# Problem Overview


I am a newbie and trying to understand concepts of inheritance and design patterns.

I came across this pattern http://en.wikipedia.org/wiki/Strategy_pattern when I was going through some blog.

I found it interesting and wanted to learn more. So I developed the following program.

static void Main(string[] args)
{
	Context context;

	// Three contexts following different strategies
	context = new Context(new ConcreteStrategyAdd());
	int resultA = context.executeStrategy(3, 4);

	context = new Context(new ConcreteStrategySubtract());
	int resultB = context.executeStrategy(3, 4);

	context = new Context(new ConcreteStrategyMultiply());
	int resultC = context.executeStrategy(3, 4);

	Console.Read();
}      

abstract class Strategy
{
	public abstract int execute(int a, int b);

	public void Test()
	{
		Console.Write("tttt");
	}
}

class ConcreteStrategyAdd : Strategy
{
    public override int execute(int a, int b)
    {
        Console.WriteLine("Called ConcreteStrategyAdd's execute()");
        return a + b;  // Do an addition with a and b
    }
}

class ConcreteStrategySubtract : Strategy
{

    public override int execute(int a, int b)
    {
        Console.WriteLine("Called ConcreteStrategySubtract's execute()");
        return a - b;  // Do a subtraction with a and b
    }
}

class ConcreteStrategyMultiply : Strategy
{
    public override int execute(int a, int b)
    {
        Console.WriteLine("Called ConcreteStrategyMultiply's execute()");
        return a * b;   // Do a multiplication with a and b
    }
}

class Context
{
    private Strategy strategy;

    // Constructor
    public Context(Strategy strategy)
    {
        this.strategy = strategy;
    }

    public int executeStrategy(int a, int b)
    {
        return strategy.execute(a, b);
    }
}

The program compiles fine and is working. But my question is how is it possible to pass derived class as a parameter when the Context constructor is expecting base class as a parameter? Is the casting happening implicitly? Why does the compiler does not error?

context = new Context(new ConcreteStrategyAdd());  

public Context(Strategy strategy)
{
	this.strategy = strategy;
}

C# Solutions


Solution 1 - C#

Put really simply:

> A Derived class (or subclass) is an instance of its base class.

So, when you pass an instance of ConcreteStrategyAdd into the constructor, you are essentially passing a Strategy object in.

There is no casting involved. The type hierarchy allows for this type of programming. It allows programmers to use polymorphism in their code.

Solution 2 - C#

There is no casting needed, since ConcreteStrategyAdd is a Strategy - it satisfies all the requirements of being a Strategy. This is the principle of Polymorphism.

Perhaps a more simplistic example is needed:

abstract class Fruit { }

class Apple : Fruit { }
class Orange : Fruit { }
class Melon : Fruit { }

class FruitBasket
{
    void Add(Fruit item) { ... }
}

FruitBasket basket = new FruitBasket();
basket.Add(new Apple()); // Apple IS A fruit
basket.Add(new Orange()); // Orange IS A fruit
basket.Add(new Melon()); // Melon IS A fruit

class Potato : Vegetable { }

basket.Add(new Potato()); // ERROR! Potato IS NOT A fruit.

Solution 3 - C#

The derived class is a base class. (That's the whole concept of inheritance: inheritance defines an 'is a' relationship).

Also, check out the Liskov substitution principle. :)

Solution 4 - C#

its easier to understand if you use a more simplistic example than the strategy pattern.

suppose you have a class called "Fruit" and a class called "Apple" that derives from fruit. any method that is written to work with Fruit in general can work just fine with an Apple or any other specific type of fruit

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSandeepView Question on Stackoverflow
Solution 1 - C#jjnguyView Answer on Stackoverflow
Solution 2 - C#MattDaveyView Answer on Stackoverflow
Solution 3 - C#Frederik GheyselsView Answer on Stackoverflow
Solution 4 - C#Robert LevyView Answer on Stackoverflow