2011-03-01 12 views
0

私は相続に関する質問があるので、私は、以下のシナリオについて説明します:私は、ログを含むテキストファイルを読んでいます継承と複数のコンストラクタ

を。 各ログ行の形式は次のとおりです。 「日付タイプの説明」

ただし、ログの「タイプ」によっては、「説明」を別に解析してさまざまな分野のアウト。ここで

は、いくつかの例は以下のとおりです。

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

- だから、私は何をしようとしたことは、このでした: "パターンに応じて、それ-parse
ログのラインアウト-get
日付タイプ説明Type "フィールド」で
-look"、および必要に応じて新しいオブジェクト/パース記述を作成

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回解析する必要はありません。 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); 
    } 
} 

を使用し、なぜ少しだけこのような何かをしない、私のコメントを1として

String line = ReadFileAndGetLine(); // Get a line from the file 
    Log log = LogFactory.Create(line); 
+1

条件解析を行うのに「ログ」を使用しないのはなぜですか? –

+0

@失望:各タイプのログには異なるパラメータがあるため、「Field1、Field2、Field3など」を入れたくありませんでした。必要でない場合は「ログ」のオブジェクト – Eric

+1

評価しましたが、常に 'Type'と' Description'を含んでいれば、これは引き続き基本クラスで発生します。 –

答えて

2

を使用しようとする

+0

しかし、 "Field1、Field2など"をどのように格納するのか分かりません。パラメーター? - "Description"には3つの文字列が含まれているか、DateTimeとDoubleなどが含まれている可能性があります。 – Eric

+0

私はあなたの2番目の試行がはるかに優れています。実際は抽象ファクトリーのように見えます。私はこれがもっと進んでいると思う。ありがとう。 – Eric

+0

問題はありませんが、特定のケースに適していると思います。 'LogEntry'から' InnerLogEntry'を派生させて、すべてのエントリが基本的なデータセットや必要に応じて独自の子を持つようにすることもできます。 –

4

試してみてください。

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

I派生クラスにフィールドがあることに注意してください。ただし、説明はここで解析できます。しかし、実際にはが知っているところを知ることができる理由を知ることができます。説明を解析する必要がある場合は、別の回答で提案されている工場パターンを使用するか、 - しかし、強いタイピングから逃げ出してしまうのは、今日は一般的に眉をひそめている、と私は思う。

もう一つの提案は、あなたの最初の試みに非常に似ていますが、分離されたクラスではこのようなものを扱うのではなく、型の管理をカプセル化する傾向があります。(表面的に)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 
     } 
    } 
+0

ありがとうございます。 "GetType(line)"を2回呼び出すことなく、フィールド "Date"と "Type"を保持する方法はありますか? InformationLog(line)のコンストラクタがGetType(line)を再度呼び出さなければならないようです。 – Eric

+0

次に、コンストラクタを 'Log(String line、string type)'に拡張することができます。 – Stecya