c# - polimorfismo - Pasar Clase derivada como parámetro a un método cuando el tipo de parámetro es clase base
herencia en java (4)
En pocas palabras:
Una clase derivada (o subclase) es una instancia de su clase base.
Entonces, cuando pasas una instancia de ConcreteStrategyAdd
al constructor, esencialmente estás pasando un objeto de Strategy
en.
No hay casting involucrado. La jerarquía de tipos permite este tipo de programación. Permite a los programadores usar polymorphism en su código.
Soy un novato e intento comprender los conceptos de herencia y patrones de diseño.
Me encontré con este patrón http://en.wikipedia.org/wiki/Strategy_pattern cuando estaba pasando por algún blog.
Lo encontré interesante y quería aprender más. Entonces desarrollé el siguiente programa.
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);
}
}
El programa compila bien y está funcionando. Pero mi pregunta es ¿cómo es posible pasar la clase derivada como un parámetro cuando el constructor de Context
espera la clase base como un parámetro? ¿El casting está sucediendo implícitamente? ¿Por qué el compilador no tiene errores?
context = new Context(new ConcreteStrategyAdd());
public Context(Strategy strategy)
{
this.strategy = strategy;
}
La clase derivada es una clase base. (Ese es todo el concepto de herencia: la herencia define una relación ''es una'').
Además, revisa el principio de sustitución de Liskov . :)
No se necesita moldear, ya que ConcreteStrategyAdd es una Estrategia: satisface todos los requisitos de ser una Estrategia. Este es el principio del polimorfismo.
Tal vez se necesite un ejemplo más simplista:
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.
es más fácil de entender si utiliza un ejemplo más simplista que el patrón de estrategia.
supongamos que tiene una clase llamada "Fruta" y una clase llamada "Manzana" que se deriva de la fruta. cualquier método que se escriba para trabajar con Fruit en general puede funcionar bien con una manzana o cualquier otro tipo específico de fruta