Наследование и множественные конструкторы - PullRequest
0 голосов
/ 01 марта 2011

У меня есть вопрос относительно наследования, поэтому я опишу следующий сценарий:

Я читаю текстовый файл, содержащий журналы. (Один журнал на строку) Каждая строка журнала будет иметь следующий формат: «Описание типа даты»

Однако, в зависимости от «Типа» журнала, мне придется разбирать «Описание» по-разному и извлекать разные поля.

Вот несколько примеров:

5/1/2011 Information Field1, Field2, Field3
5/2/2011 Error       Field1

- Итак, я попытался сделать следующее:
-Получить строку из журнала
Разрежьте его по шаблону «Описание типа даты»
-Смотрите в поле «Тип» и создайте новые объекты / описание разбора при необходимости

public class Log
{
   public DateTime Date;
   public String Type;
   public String Description;

   public Log(String line)
   {
      this.Date = GetDate();
      this.Type = GetType();
      this.Description = GetDescription();
   }
}

public class InformationLog : Log
{
   public String Field1;
   public String Field2;
   public String Field3;

   public InformationLog(Log log)
   {
      this.Field1 = GetField1(log.Description);
      this.Field1 = GetField2(log.Description);
      this.Field1 = GetField3(log.Description);
   }
}

public class Client
{
   public void Main()
   {
       String line = ReadFileAndGetLine();  // Get a line from the file
       Log log = new Log(line);
       if(log.Type == "Information")
          log = new InformationLog(log);    // Is this right?
   }
}

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

Мой вопрос: Есть ли стандартный способ сделать это? Или что-то не так с этой реализацией?

-
Edit:
Кроме того, я должен упомянуть: я рассуждал о том, что я однажды проанализирую строку, чтобы получить дату и тип, а затем снова проанализирую ее, чтобы получить более точные сведения.
Я решил использовать наследование, чтобы мне не приходилось анализировать поля Date и Type дважды.

Ответы [ 2 ]

4 голосов
/ 01 марта 2011

Попробуйте использовать Заводской шаблон

static class LogFactory
{
    public static Log Create(String line)
    {
        if(GetType(line) == "Information")
           return CreateInformationLog(line);
        return CreateLog(line);
    }

    private static Log CreateLog(String line)
    {
       return new Log(line);
    }

    private static Log CreateInformationLog(String line)
    {
       return new InformationLog(line);
    }
}

А потом попробуй использовать

   String line = ReadFileAndGetLine();  // Get a line from the file
   Log log = LogFactory.Create(line);
2 голосов
/ 01 марта 2011

Согласно моему комментарию, почему бы просто не сделать что-то вроде этого:

    public enum LogEntryType
    {
        Error = -1,
        Information = 0,
    }

    public class LogEntry
    {
        public string Raw;
        public DateTime Date;
        public LogEntryType Type;
        public string Description;

        public LogEntry(String line)
        {
            Raw = line;
            Date = ParseDate();
            Type = ParseType();
            Description = ParseDescription();
        }

        public string ParseDescription()
        {
           var result = string.Empty;
           switch(Type)
           {
               case LogEntryType.Error:
                   //parse here
                   break;
               case LogEntryType.Information:
                   //parse here
                   break;
           }
           return result;
        }
    }

Я заметил, что у вас есть поля в производном классе, но описание может быть проанализировано здесь;хотя я могу понять, почему люди могут захотеть перенести его в то место, которое на самом деле знает , как следует анализировать описание, и в этом случае вы можете использовать шаблон фабрики, предложенный в другом ответе, или реализовать свойство 'Я полагаю, что сценарий типа «сумка» - но отход от строгой типизации обычно не одобряется.

Другое предложение, хотя и очень похожее на вашу первоначальную попытку, имеет тенденцию заключать в себе управление типами, а неотдельный класс обрабатывает такие вещи - шаблон немного (поверхностно), такой как Exception, где у вас есть корневая запись и внутренние записи:

    public enum LogEntryType
    {
        Error = -1,
        Information = 0,
    }

    public class LogEntry
    {
        public string Raw;
        public DateTime Date;
        public LogEntryType Type;
        public string Description;

        public InnerLogEntry InnerEntry;

        public LogEntry(String line)
        {
            Raw = line;
            Date = ParseDate();
            Type = ParseType();
            //parse the 'raw' description...
            Description = ParseDescription();
            //determine the inner entry type...
            switch (Type)
            {
                case LogEntryType.Error:
                    InnerEntry = new ErrorLogEntry(this);
                    break;
                case LogEntryType.Information:
                    InnerEntry = new InformationLogEntry(this);
                    break;
            }                
        }
    }

    public abstract class InnerLogEntry
    {
        protected LogEntry Parent;

        public InnerLogEntry(LogEntry logEntry)
        {
            Parent = logEntry;
        }
    }

    public class InformationLogEntry : InnerLogEntry
    {
        public InformationLogEntry(LogEntry logEntry)
            : base(logEntry)
        {
            //parse custom data
        }
    }

    public class ErrorLogEntry : InnerLogEntry
    {
        public ErrorLogEntry(LogEntry logEntry)
            : base(logEntry)
        {
            //parse custom data
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...