2015-07-15 5 views
0

У меня такой же код в методе 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; 
    } 

} 
+0

Суперкласс, который имеет метод 'Output()'. Тогда ваши методы «День» и «Час» расширят его. Конечно, вашему суперклассу нужны объекты «Дата» и «Время». – gh0st

ответ

6

Не совершайте ошибку создания базового класса, чтобы разделить этот метод. Это распространенное злоупотребление наследованием. Эта техника вообще ломается, и вы вводите бессмысленный класс в публичный интерфейс вашего класса. Наследование не для совместного использования кода. Это для «замены Лискова».

Вместо этого создайте статический вспомогательный метод, который принимает оба значения в качестве аргументов и вычисляет результат. Это позволяет вам выполнить форматирование один раз. Это очень легко реализовать, работает почти всегда и не влияет на публичный API ваших классов. Не бойтесь немного большего размера синтаксиса. Это не значительная проблема (большую часть времени).

+2

спасибо, что посмотрели – Ronin

-1

просто унаследовать класс, который имеет, что открытый член :)

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

Не будет ли класс 'HasOutput' знать, что такое' Date' и 'Time'? – gh0st

+0

Правда, общая идея по-прежнему подходит, хотя – maksymiuk

+0

Вы могли бы реализовать идею в рабочем коде, пожалуйста? – Ronin

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

1

В качестве альтернативы ответу usr вы можете реорганизовать свой код, чтобы беспокоить запись данных на экран отдельно.

Так что ваши Hour и Day классов не имеют 2 обязанностей (Single Ответственность принцип), а также делают код намного проще обновить с более сложной выходной функциональностью в будущем, так как у вас есть только изменить код класс писателя. (или отрисуйте его и создайте, например, 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); 
    } 
} 
Смежные вопросы