简体   繁体   English

如何覆盖方法保存模板方法模式

[英]How to Override a Method Saving Template Method Pattern

I do have an abstract class where on the constructor I'm calling an abstract method declared on the very same class, and Im doing this because I do want to force all the derivated class to not just implement my abstract method but also call it (I think here is where the Template Method pattern comes in). 我确实有一个抽象类,在构造函数上,我要在同一类上声明一个抽象方法,而我这样做是因为我想强迫所有派生类不仅实现我的抽象方法,而且还要调用它(我认为这是Template Method模式出现的地方。

BTW: I know it is not the best approach to make sure all things will be correctly writen but due external problems I would like to minimize my future problems with bad implementation. 顺便说一句:我知道这不是确保所有内容都能正确写入的最佳方法,但是由于外部问题,我希望通过不好的实施来减少以后的问题。 The snippet is below: 该代码段如下:

public abstract class Generic
{
    public Generic()
    {
        Console.WriteLine("This is the generic");

        this.SetRules();
    }

    protected abstract void SetRules();
}

Well, on one of my derivated class need to set up a private variable on the declaration, and I would like to use this variable inside the overriden method. 好吧,在我的派生类之一上,需要在声明上设置一个私有变量,我想在重写方法中使用此变量。 As I don't know how many possibilities I would need to each one of my derivated classes, I would like to declare it inside each one of my derivated class as necessary. 由于我不知道我的每个派生类都需要多少可能性,因此我想根据需要在每个我的派生类中声明它。 An example below: 下面的例子:

public class Derivated2 : Generic
{
    private int _parameter;

    public Derivated2(int parameter)
    {
        this._parameter = parameter;
    }

    protected override void SetRules()
    {
        int x = 0;
        x = 1 + 3;

        Console.WriteLine(String.Concat("This is the derivated2 with x: ", x, "; _parameter: ", _parameter));
    }
}

Now to the problem; 现在解决问题;

When I'm calling my derivated2 class, I can't use/see my variable value specified on declaraion: 当我调用派生类2时,无法使用/查看在声明中指定的变量值:

public static void Main()
{
    Derivated2 _class1 = new Derivated2(2);
}

My output is: 我的输出是:

This is the generic
This is the derivated2 one with x: 4; _parameter: 0

How can I see/use my variable on my overriden asbtract method? 如何在覆盖的asbtract方法上查看/使用变量? If I can't, What would be the best approach to reach my goal securing the SetRules method is going to be called no matter what the developer does and also can use private variables inside his derivated class? 如果我做不到,那么不管开发人员做什么,也可以调用确保SetRules方法安全的最佳方法是什么,并且还可以在其派生类中使用私有变量?

Here is the full code I have done: 这是我完成的完整代码:

Calling SetRules on Abstract Generic Class 在抽象泛型类上调用SetRules

Calling SetRules on Derivated Class 在派生类上调用SetRules

The problem is you are calling the Generic constructor which will call SetRules before your Derivated2 constructor is called meaning your parameter has not been set yet. 问题是您正在调用Generic构造函数,该构造函数将在调用Derivated2构造函数之前调用SetRules,这意味着尚未设置参数。 You could try this. 你可以试试看。

public abstract class Generic
{
    public Generic(int parameter)
    {
        Console.WriteLine("This is the generic");

        this.SetRules(parameter);
    }

    protected abstract void SetRules(int paramter);
}

public class Derivated2 : Generic
{

    public Derivated2(int parameter) : base(parameter){ }

    protected override void SetRules(int parameter)
    {
        int x = 0;
        x = 1 + 3;

        Console.WriteLine(String.Concat("This is the derivated2 with x: ", x, "; _parameter: ", parameter));
    }
}
public static void Main()
{
    Derivated2 _class1 = new Derivated2(2);
}

As you said it wouldn't be nice to have to call SetRules every time you want to create a new class so this would mean you wouldn't have to (quickly threw this together so you will need to fix it up) 正如您所说,每次要创建一个新类都必须调用SetRules并不是很好,所以这意味着您不必(迅速将其放在一起,因此需要对其进行修复)

public abstract class Generic
{
    public Generic()
    {
        Console.WriteLine("This is the generic");
    }

    public abstract void SetRules();
}

public sealed class Derivated2 : Generic
{
    int _param;

    public Derivated2(RulesWithParameters rules) {
        _param = rules.Parameter;
    }

    public override void SetRules()
    {
        int x = 0;
        x = 1 + 3;

        Console.WriteLine(String.Concat("This is the derivated2 with x: ", x, "; _parameter: ", _param));
    }
}
public void Main()
{
    var rules = new RulesWithParameters{
        Parameter = 5
    };
    var _class1 = FactoryMethod<Derivated2>(rules);

    var _class2 = FactoryMethod<Derivated1>(null);
}

public class Derivated1 : Generic
{
    public Derivated1(Rules rules)
    {

    }
    public override void SetRules()
    {
        Console.WriteLine("This is the derivated1");
    }
}
public class Rules
{
    public string RuleName {get; set;}
}

public class RulesWithParameters : Rules{
    public int Parameter { get; set;}
}

public Generic FactoryMethod<T>(Rules rules) where T : Generic
{
    T instance = (T)Activator.CreateInstance(typeof(T), rules);;
    instance.SetRules();
    return instance;
}

I guess constructors in C# are not polymorphic, so you cannot call an overridable method from your constructor. 我想C#中的构造函数不是多态的,所以您不能从构造函数中调用可重写的方法。 You can read this piece of documentation: MSDN article . 您可以阅读以下文档: MSDN文章

Also it seems as a bad practice to me to use such approach in general. 通常,使用这种方法对我来说似乎是一个坏习惯。 The abstract class's constructor is not aware of your descendant class's details of implementation, and should not be, so it is not correct to put there initialization of Derivated2. 抽象类的构造函数不知道您的后代类的实现详细信息,因此也不应了解,因此在其中放置Derivated2的初始化是不正确的。 Try to place initialization code somewhere else. 尝试将初始化代码放在其他位置。

If the SetRules method could be static instead of instance maybe you can add a static constructor and inside that constructor you can call the SetRules method. 如果SetRules方法可以是静态的而不是实例,则可以添加静态构造函数,并且可以在该构造函数内调用SetRules方法。 If not the Factory idea seems to be the best clean approach. 如果不是的话,工厂的想法似乎是最好的清洁方法。

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

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