如何避免代码重复?

How to avoid code repeating?

我在 类 HourDay 的方法 Output() 中有相同的代码。 有没有办法避免在一个地方而不是两个地方更改代码?

class Program
{
    static void Main(string[] args)
    {
        Hour hour = new Hour("20150715 080000");
        Day day = new Day(hour);

        Console.WriteLine(String.Format("Hour: {0}", hour.Output()));
        Console.WriteLine(String.Format("Day: {0}", day.Output()));
    }
}

public interface IMoment
{
    string OutputMoment();
}

class Hour : IMoment
{
    public string Date;
    public string Time;

    public Hour (string s)
    {
        string[] parts = s.Split(';');
        this.Date = parts[0];
        this.Time = parts[1];
    }

    public string Output()
    {
        return Date + " " + Time;
    }
}

class Day : IMoment
{
    public string Date;
    public string Time;

    public Day(Hour hour)
    {
        this.Date = hour.Date;
        this.Time = hour.Time;
    }

    public string Output()
    {
        return Date + " " + Time;
    }

}

只需继承具有 public 成员的 class :)

class HasOutput
{
    public string Date;
    public string Time;

    public string Output()
    {
        return Date + " " + Time;
    }
}

class Hour : HasOutput, IMoment
{
    public Hour (string s)
    {
        string[] parts = s.Split(';');
        this.Date = parts[0];
        this.Time = parts[1];
    }
}

class Day : HasOutput
{
    public Day(Hour hour)
    {
        this.Date = hour.Date;
        this.Time = hour.Time;
    }
}

你应该做一个 abstract class 而不是 interface:

class Program
{
    static void Main(string[] args)
    {
        Hour hour = new Hour("20150715;080000");
        Day day = new Day(hour);

        Console.WriteLine(String.Format("Hour: {0}", hour.OutputMoment()));
        Console.WriteLine(String.Format("Day: {0}", day.OutputMoment()));
    }
}

public abstract class Moment
{
    public string Date;
    public string Time;

    public virtual string OutputMoment()
    {
        return Date + " " + Time;
    }

    public override string ToString()
    {
        return OutputMoment();
    }
}

class Hour : Moment
{
    public Hour(string s)
    {
        string[] parts = s.Split(';');
        this.Date = parts[0];
        this.Time = parts[1];
    }
}

class Day : Moment
{
    public Day(Hour hour)
    {
        this.Date = hour.Date;
        this.Time = hour.Time;
    }
}

OutputMoment() 标记为 virtual 也将允许您在需要时覆盖默认实现。我还覆盖了 ToString() 这样你就可以做类似 Console.WriteLine(hour); 的事情而不必调用 OutputMoment()

不要错误地创建基础 class 来共享该方法。这是对继承的常见滥用。这种技术通常会失效,您会在 class 的 public 界面中引入无意义的 class。 继承不是为了代码共享。它是为了"Liskov substitution"。

相反,创建一个静态辅助方法,它将两个值作为参数并计算结果。这允许您实施一次格式化。这很容易实现,几乎总是有效,并且不会影响 classes 的 public API。不要害怕稍大的语法足迹。这不是什么大问题(大多数时候)。

作为 usr 答案的替代方案,您可以重构您的代码,将数据写入屏幕的问题分开。

所以你的 HourDay classes 没有 2 个职责(单一职责原则),也使得代码更容易更新更复杂的输出将来的功能,因为您只需要更改编写器中的代码 class。 (或将其抽象化并为 FileMomentWriter 等创建)

public interface IMoment
{ 
   string MomentType {get;}
   string Date {get;set;}
   string Time {get;set;}
}


public class Hour:IMoment
{
    public string MomentType {get{return "Hour";}}
    public string Date {get;set;}
    public string Time {get;set;}

    public Hour (string s)
    {
        string[] parts = s.Split(';');
        this.Date = parts[0];
        this.Time = parts[1];
    }
}

public class Day: IMoment
{
    public string MomentType {get{return "Day";}}
    public string Date{get;set;}
    public string Time{get;set;}

    public Day(Hour hour)
    {
        this.Date = hour.Date;
        this.Time = hour.Time;
    }
}

public class ConsoleMomentWriter
{
   public void Write(IMoment moment)
   {
      Console.WriteLine("{0}: {1} {2}",moment.MomentType,moment.Date,moment.Time);
   }
}

class Program
{
    static void Main(string[] args)
    {
        Hour hour = new Hour("20150715 080000");
        Day day = new Day(hour);
        var writer = new ConsoleMomentWriter();
        writer.Write(hour);
        writer.Write(day);
    }
}