Как переопределить метод Сохранение шаблона Шаблон метода - PullRequest
0 голосов
/ 02 января 2019

У меня есть абстрактный класс, где в конструкторе я вызываю абстрактный метод, объявленный в том же классе, и я делаю это, потому что я хочу заставить весь производный класс не только реализовать мой абстрактный метод, но иназовите это (я думаю, что именно здесь появляется шаблонный метод).

Кстати: я знаю, что это не лучший подход, чтобы гарантировать, что все вещи будут написаны правильно, но из-за внешних проблем я хотел бы свести к минимумумои будущие проблемы с плохой реализацией.Ниже приведен фрагмент кода:

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

        this.SetRules();
    }

    protected abstract void SetRules();
}

Что ж, на одном из моих производных классов нужно установить в объявлении частную переменную, и я хотел бы использовать эту переменную внутри переопределенного метода.Поскольку я не знаю, сколько возможностей мне понадобится для каждого из моих производных классов, я хотел бы объявить его внутри каждого из моих производных классов по мере необходимости.Пример ниже:

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));
    }
}

Теперь к проблеме;

Когда я вызываю свой класс производного2, я не могу использовать / увидеть значение моей переменной, указанное в объявлении:

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

Мой вывод:

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

Как я могу увидеть / использовать мою переменную в переопределенном методе asbtract?Если я не могу, какой будет наилучший подход для достижения моей цели, и будет вызываться защита метода SetRules независимо от того, что делает разработчик, а также может использовать закрытые переменные внутри своего производного класса?

Вотполный код, который я сделал:

Вызов SetRules для абстрактного универсального класса

Вызов SetRules для производного класса

Ответы [ 3 ]

0 голосов
/ 02 января 2019

Я предполагаю, что конструкторы в C # не являются полиморфными, поэтому вы не можете вызвать переопределенный метод из вашего конструктора. Вы можете прочитать эту часть документации: Статья MSDN .

Также мне кажется плохой практикой использовать такой подход в целом. Конструктор абстрактного класса не знает подробностей реализации вашего класса-потомка, и не должен этого знать, поэтому некорректно помещать туда инициализацию Derivated2. Попробуйте разместить код инициализации где-нибудь еще.

0 голосов
/ 02 января 2019

Если метод SetRules может быть статическим, а не экземпляром, возможно, вы можете добавить статический конструктор, а внутри этого конструктора вы можете вызвать метод SetRules.Если нет, то Фабричная идея кажется лучшим чистым подходом.

0 голосов
/ 02 января 2019

Проблема в том, что вы вызываете конструктор Generic, который вызовет SetRules до вызова конструктора Derivated2, то есть ваш параметр еще не установлен.Вы можете попробовать это.

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);
}

Как вы сказали, было бы неправильно вызывать 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...