Реализация стратегии для конструктора - PullRequest
1 голос
/ 01 апреля 2009

Каков наилучший способ реализации стратегии для конструктора шаблонного / абстрактного класса в C #? У меня есть несколько классов, которые все основаны на анализе строки внутри конструктора. Разбор выполняется статическим методом, который создает список пар ключ-значение и является общим для всех классов, но некоторые поля также являются общими для всех классов - поэтому я использую абстрактный шаблонный класс.

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

Edit: Добавлен не рабочий код для шаблона класса

public abstract class XXXMessageTemplate 
{
    public XXXMessageTemplate(string x) // implementation for the constructor 
   {
       Parse(x);//general parse function
       CommonFields();//filling common properties
       HandlePrivateProperties();//fill individual properties
       HandlePrivateStructures();//fill individual structures
    }
    abstract void HandlePrivateProperties();
    abstract void HandlePrivateStructures();
}

The actual messages should not implement any constructor and only implement the HandlePrivateProperties and HandlePrivateStructures functions.

Ответы [ 4 ]

7 голосов
/ 01 апреля 2009

Если вы хотите, чтобы логика конструктора базового класса выполнялась в производном классе, вы обычно просто вызываете его:

 public Derived(...) : base(...)
 {
     // ...
 }

Базовый класс может вызывать абстрактные / виртуальные методы во время конструктора, но обычно он не одобряется, поскольку тело конструктора производного класса еще не будет выполнено. (Вы хотели бы документально подтвердить это.)

Это отвечает на ваш вопрос? Я не совсем уверен, что понимаю проблему - какой-то псевдокод поможет.

EDIT: производные классы имеют для реализации конструкторов. Конструкторы не наследуются. Если вы не укажете конструктор, компилятор предоставит конструктор без параметров, который вызывает базовый конструктор без параметров. Однако вы можете легко написать конструктор с той же сигнатурой и просто вызвать конструктор базового класса:

public Derived(string x) : base(x)
{
    // Base constructor will do all the work
}
2 голосов
/ 01 апреля 2009

Укажите конструктор для базового класса и используйте его в производных классах:

abstract class Base {
     // ...
     protected Base(string commonField) {
        CommonField = commonField;
     }
}

class Derived1 : Base {
     public Derived1(string commonField, string specificField) : base(commonField) {
        SpecificField = specificField;
     }
}
1 голос
/ 01 апреля 2009

Как я вижу, проблема в методе Parse (...). Не в самом методе, а в его существовании. У вас есть некоторые необработанные данные (строка x), которые необходимо преобразовать в структурированные данные (пары ключ-значение) перед использованием для построения объектов. Поэтому вам нужно как-то передать структурированные данные в базовые и дочерние конструкторы. Я вижу 3 подхода:

  1. Анализ данных в базовом классе и использование защищенного базового свойства для передачи их дочерним элементам.
  2. Анализировать данные перед вызовом конструктора.
  3. Разбор данных по месту использования.

1 Вы можете расширить ответ Mehrdad через дополнительное защищенное свойство, которое содержит проанализированные аргументы. Что-то вроде:

abstract class Base {
     protected ParsedData ParsedData;
     // ...
     protected Base(string x) {
        ParsedData = Parse(x);
        CommonFields(); //initialize common fields using ParsedData
     }
}

class Derived1 : Base {
     public Derived1(string x) : base(x) {
        DerivedFields(); //initialize specific fields using ParsedData
     }
}

2 Или вы можете передать предварительно проанализированную строку в конструктор:

abstract class Base {
     protected ParsedData ParsedData;
     // ...
     public static ParsedData Parse(string x)
     {
        //Parse x here...
     }

     protected Base(ParsedData data) {
        CommonFields(data); //initialize common fields using data
     }
}

class Derived1 : Base {
     public Derived1(ParsedData data) : base(data) {
        DerivedFields(data); //initialize specific fields using data
     }
}

3 Или разобрать в месте использования:

abstract class Base {
     // ...
     protected Base(string x) {
        var data = Parse(x);
        CommonFields(data); //initialize common fields using data
     }
}

class Derived1 : Base {
     public Derived1(string x) : base(x) {
        var data = Parse(x);
        DerivedFields(data); //initialize specific fields using data
     }
}
1 голос
/ 01 апреля 2009

Я не уверен на 100%, что полностью понимаю вопрос, но вы хотите сказать, что вы хотите, чтобы ваши подклассы передавали буквенную строку в базу, как в этом примере?

public class MyMessage : XXXMessageTemplate
{
    public MyMessage() : base("MyMessage String")
    {
    }

    public override void HandlePrivateProperties()
    {
        // ...
    }

    public override void HandlePrivateStructures()
    {
        // ...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...