如何避免代码重复?

时间:2015-07-15 20:57:13

标签: c# .net code-duplication

我在Output()Hour类中的方法Day中使用相同的代码。 有没有办法避免它在一个地方而不是两个地方改变代码?

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

}

4 个答案:

答案 0 :(得分:6)

不要错误地创建基类来共享该方法。这是继承的常见滥用。这种技术一般会中断,你会在类的公共接口中引入一个无意义的类。 继承不适用于代码共享。适用于“Liskov替换”。

相反,创建一个静态辅助方法,它将两个值作为参数并计算结果。这允许您实现一次格式化。这很容易实现,几乎总是有效,并且不会影响类的公共API。不要害怕稍大的语法占用空间。这不是一个重大问题(大部分时间)。

答案 1 :(得分:1)

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

因此,您的HourDay课程不具备2项职责(单一责任原则),并且使代码更容易在未来使用更复杂的输出功能进行更新,因为您只需要更改writer类中的代码。 (或抽象它并创建例如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);
    }
}

答案 2 :(得分:0)

您应该制作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()

答案 3 :(得分:-1)

只是继承一个具有该公共成员的类:)

Promise.delay