Передача класса Derived в качестве параметра для метода, когда тип параметра является базовым классом
Я новичок и пытаюсь понять концепции наследования и шаблонов проектирования.
Я встретил этот шаблон http://en.wikipedia.org/wiki/Strategy_pattern, когда я проходил через какой-то блог.
Я нашел это интересным и хотел узнать больше. Поэтому я разработал следующую программу.
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 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 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 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);
}
}
Программа компилируется и работает. Но мой вопрос в том, как можно передать производный класс как параметр, когда конструктор Context
ожидает базовый класс в качестве параметра? Является ли кастинг случаем неявно? Почему компилятор не выполняет ошибку?
context = new Context(new ConcreteStrategyAdd());
public Context(Strategy strategy)
{
this.strategy = strategy;
}
Ответы
Ответ 1
Положите просто:
A Производный класс (или подкласс) - это экземпляр его базового класса.
Итак, когда вы передаете экземпляр ConcreteStrategyAdd
в конструктор, вы по существу передаете объект Strategy
.
В игре нет участия. Иерархия типов позволяет использовать этот тип программирования. Это позволяет программистам использовать polymorphism в своем коде.
Ответ 2
Нет необходимости в кастинге, так как ConcreteStrategyAdd - это стратегия - она удовлетворяет всем требованиям стратегии. Это принцип полиморфизма.
Возможно, необходим более упрощенный пример:
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.
Ответ 3
Производный класс является базовым классом. (Что вся концепция наследования: наследование определяет отношение "есть" ).
Кроме того, ознакомьтесь с принципом замены Лискова.:)
Ответ 4
его легче понять, если вы используете более упрощенный пример, чем шаблон стратегии.
Предположим, у вас есть класс под названием "Фрукты" и класс под названием "Яблоко", который происходит от фруктов. любой метод, который написан для работы с Fruit в целом, может отлично работать с Apple или любым другим конкретным видом фруктов