Подтвердить что ты не робот

Передача класса 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;
    }
4b9b3361

Ответ 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 или любым другим конкретным видом фруктов