简体   繁体   English

使用委托和继承定义哪个方法在子类中运行

[英]Using delegate and inheritance to define which method is run inside the child class

I have a child and a parent class in C#. 我在C#中有一个孩子和一个父类。 I want to point the Calc delegate to one of several methods. 我想将Calc委托指向几种方法之一。 this is determined each time the Reset() method is called. 这是在每次调用Reset()方法时确定的。 Below is a working example. 下面是一个工作示例。 However, I want this functionality of pointing the delegate to reside on the Parent class. 但是,我希望这种指向委托的功能驻留在Parent类上。 Since the parent does not contain the methods, I don't know how to do it... 由于父级不包含方法,因此我不知道该怎么做...

    class Program
{
    static void Main(string[] args)
    {
        Model Model = new Model();
        Model.Env1 = true;
        Child Ch = new Child(Model);
        Ch.Reset();
        Ch.Calc(); Ch.Calc(); Ch.Calc();
        Console.WriteLine();
        Model.Env1 = false;
        Ch.Reset();
        Ch.Calc(); Ch.Calc(); Ch.Calc();
        Console.ReadLine();
    }
}

public class Parent
{
    public Model Model { get; set; }
    public Parent(Model model)
    {
        Model = model;
    }
    public delegate void StateHandler();
    public StateHandler Calc;
}
public class Model
{
    public bool Env1 { get; set; }
}
public class Child : Parent, IChild
{
    public Child (Model model)
        : base (model)
    {
    }
    public void Reset()
    {
        if (Model.Env1)
            Calc = CalcHeavy;
        else
            Calc = CalcLight;
    }
    public void CalcHeavy()
    {
        Console.WriteLine("CalcHeavy is active");
    }
    public void CalcLight()
    {
        Console.WriteLine("CalcLight is active");
    }
}
public interface IChild
{
    void CalcHeavy();
    void CalcLight();
}

One way to do that would be to have the Child class inject its methods into the Parent at construction time. 一种实现方法是让Child类在构造时将其方法注入Parent。 That way, the Parent class makes the choice, but the Child class defines the functionality: 这样, Parent类做出选择,而Child类定义功能:

public class Parent
{
    private readonly Action _env1Method;
    private readonly Action _notEnv1Method;
    private readonly Model _model;

    public Parent(Model model, 
                  Action env1Method, 
                  Action notEnv1Method)
    {
        _model = model;
        _env1Method = env1Method;
        _notEnv1Method = notEnv1Method;
        Reset();
    }

    public Action Calc { get; private set; }

    public void Reset()
    {
        Calc = _model.Env1 ? _env1Method : _notEnv1Method;
    }
}

public class Model
{
    public bool Env1 { get; set; }
}

public class Child : Parent
{
    public Child (Model model) : base (model, CalcHeavy, CalcLight) {}

    private static void CalcHeavy()
    {
        Console.WriteLine("CalcHeavy is active");
    }

    private static void CalcLight()
    {
        Console.WriteLine("CalcLight is active");
    }
}

Also, I'd get rid of StateHandler and just use Action instead. 此外,我将摆脱StateHandler而仅使用Action Don't create a new delegate when a standard one exists already. 如果已经存在标准委托,则不要创建新委托。

While trying to get the answer I liked to work, I managed to solve it in a different way by making the Parent abstract, and it works. 在尝试获得我喜欢的答案时,我设法通过使Parent抽象化来以不同的方式解决它,并且它起作用了。

    class Program
{
    static void Main(string[] args)
    {
        Model Model = new Model();
        Model.Env1 = true;
        Child Ch = new Child(Model);

        Ch.Calc(); Ch.Calc(); Ch.Calc();
        Console.WriteLine();
        Model.Env1 = false;

        Ch = new Child(Model);
        Ch.Calc(); Ch.Calc(); Ch.Calc();
        Console.ReadLine();
    }
}

public abstract class Parent
{
    public Model Model { get; set; }
    public Parent(Model model)
    {
        Model = model;
        if (Model.Env1)
            Calc = CalcHeavy;
        else
            Calc = CalcLight;
    }

    public Action Calc;

    public abstract void CalcHeavy();
    public abstract void CalcLight();

}
public class Model
{
    public bool Env1 { get; set; }
}
public class Child : Parent
{
    public Child(Model model) : base(model) { }

    public override void CalcHeavy()
    {
        Console.WriteLine("CalcHeavy is active");
    }
    public override void CalcLight()
    {
        Console.WriteLine("CalcLight is active");
    }
}

One way is to move the "Reset" method to the parent class and do something like this: 一种方法是将“ Reset”方法移至父类并执行以下操作:

public void Reset()
{
       var child = this as IChild;

        if (child != null && Model.Env1)
            Calc = child.CalcHeavy;
        else
            Calc = child.CalcLight;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM