Je suis un débutant et j'essaie de comprendre les concepts d'héritage et les modèles de conception.
Je suis tombé sur ce modèle http://en.wikipedia.org/wiki/Strategy_pattern lorsque je parcourais un blog.
Je l'ai trouvé intéressant et j'ai voulu en savoir plus. J'ai donc développé le programme suivant.
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);
}
}
Le programme compile bien et fonctionne. Mais ma question est de savoir comment est-il possible de passer la classe dérivée en tant que paramètre lorsque le constructeur Context
attend la classe de base en tant que paramètre? Le casting a-t-il lieu implicitement? Pourquoi le compilateur ne fait-il pas d'erreur?
context = new Context(new ConcreteStrategyAdd());
public Context(Strategy strategy)
{
this.strategy = strategy;
}
En termes simples:
Une classe dérivée (ou sous-classe) est une instance de sa classe de base.
Ainsi, lorsque vous passez une instance de ConcreteStrategyAdd
au constructeur, vous passez essentiellement un objet Strategy
dans.
Il n'y a pas de casting impliqué. La hiérarchie des types permet ce type de programmation. Il permet aux programmeurs d'utiliser polymorphisme dans leur code.
Il n'y a pas de casting nécessaire, puisque ConcreteStrategyAdd is une stratégie - il satisfait toutes les exigences d'être une stratégie. C'est le principe du polymorphisme.
Peut-être qu'un exemple plus simpliste est nécessaire:
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.
La classe dérivée est une classe de base . (C'est tout le concept de l'héritage: l'héritage définit une relation "est une").
Consultez également le principe de substitution Liskov . :)
il est plus facile à comprendre si vous utilisez un exemple plus simpliste que le modèle de stratégie.
supposons que vous ayez une classe appelée "Fruit" et une classe appelée "Apple" qui dérive du fruit. toute méthode écrite pour fonctionner avec Fruit en général peut très bien fonctionner avec un Apple ou tout autre type spécifique de fruit