当参数类型是基类时,将Derived类作为参数传递给方法

San*_*eep 46 c# inheritance

我是一个新手,并试图理解继承和设计模式的概念.

当我浏览一些博客时,我遇到了这种模式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'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);
    }
}
Run Code Online (Sandbox Code Playgroud)

该程序编译良好,正在工作.但我的问题是,当Context构造函数期望基类作为参数时,如何将派生类作为参数传递?铸造是否隐含发生?为什么编译器没有错误?

context = new Context(new ConcreteStrategyAdd());  

public Context(Strategy strategy)
{
    this.strategy = strategy;
}
Run Code Online (Sandbox Code Playgroud)

jjn*_*guy 32

简单地说:

派生类(或子类)其基类的实例.

因此,当您将一个实例传递ConcreteStrategyAdd给构造函数时,您实际上是Strategy在传递一个对象.

没有涉及铸造.类型层次结构允许这种类型的编程.它允许程序员在代码中使用多态.


Mat*_*vey 29

由于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.
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢"现实生活中的榜样".好的.汽车和水果就是很好的例子. (3认同)
  • 这是一个很好的例子,对某些人来说可能比常规的 B:A 和汽车示例更清楚。 (3认同)