继承和多个构造函数

时间:2011-03-01 14:18:40

标签: c# .net inheritance multiple-inheritance

我有一个关于继承的问题,所以我将描述下面的场景:

我正在阅读包含日志的文本文件。 (每行一个日志) 每个日志行将具有以下格式: “日期类型说明”

但是,根据日志的“类型”,我将不得不以不同的方式解析“描述”并提取不同的字段。

以下是一些例子:

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”变量将自身用作自己构造函数的参数。

我的问题是: 有这样做的标准方法吗?或者,这个实现有什么问题吗?

-
编辑:
另外,我应该提一下:我的理由是,我会解析一次该行以获取日期和类型,然后再次解析它以获得更精细的细节。
我决定使用继承,所以我不必两次解析Date和Type字段。

2 个答案:

答案 0 :(得分:4)

尝试使用Factory pattern

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

答案 1 :(得分:2)

根据我的评论,为什么不做一些像这样的事情:

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