2015-08-17 2 views
0

Скажем, у меня есть три или более класса: Инженер: Сотрудник: Лицо. Рассмотрим следующий пример (вид, что я использовать StringBuilder и другие лучшие практики в настоящее время)Многоуровневое наследование Расширяемые методы

public abstract class Person 
{ 
    public string Name{get;set;} 
    public string SaySomething() 
    { 
     string introduction = "Hello, my name is " + Name + ". "; 
     return OnSaySomething(introduction); 
    } 
    protected virtual string OnSaySomething(string thoughts) 
    { return thoughts; } 
} 

public abstract class Employee : Person 
{ 
    public string Employer{get;set;} 

    protected override string OnSaySomething(string thoughts) 
    { 
     return thoughts + "I work for " + Employer + "."; 
    } 
} 

public class Engineer : Employee 
{ 
    public string Discipline{get;set;} 

    protected override string OnSaySomething(string thoughts) 
    { 
     return thoughts + "My discipline is " + Discipline + "."; 
    } 
} 

В примере выше, выход:

Engineer engineer = new Engineer(); 
engineer.Name = "Dennis Ritchie"; 
engineer.Discipline = "Software Engineering"; 
Console.WriteLine(engineer.SaySomething()); 

даст

Здравствуйте, мой имя Деннис Ритчи. Моя дисциплина - Software Engineering.

Можно ли структурировать эти классы таким образом, что каждое переопределение «Гвозди» по большей функциональности, например, что выход:

Здравствуйте, меня зовут Денис Ритчи. Я работаю на . Моя дисциплина - Разработка программного обеспечения.

Есть ли стандартный способ реализации такой идеи? Мое решение для коленного сустава заключается в том, чтобы запечатать OnSaySomething() по адресу Employee и ввести новый метод OnEmployeeSaySomething(), который Engineer переопределит для своей конкретной логики.

Это, кажется, запутаться довольно быстро, хотя с тех пор SaySomething(), OnSaySomething() и OnEmployeeSaySomething() все выставлены на Engineer (и даже хуже, если есть другой уровень в иерархии!). Интересно, есть ли лучшее решение. Спасибо за внимание!

TL; DR: Я хочу расширить, не разрушая базовую логику. Но я не хочу, чтобы мои занятия были действительно грязными.

EDIT:

Кто-то показало хорошее (возможно очевидное) решение, которое моя вина для обеспечения плохого примера. Вместо этого, говорим, что мы проверка некоторых данных в этом виде сценария:

public class Level0 
{ 
    public string Data{get;set;} 
    public bool IsValid() 
    { 
     if (Data == null) return false; 
     else return OnIsValid(); 
    } 
    protected virtual bool OnIsValid() 
    {return true;} 
} 
public class Level1 : Level0 
{ 
    public string Data_Level1{get;set;} 
    protected override OnIsValid() 
    { 
     if (Data_level1 == null) return false; 
     else return OnLevel1IsValid(); 
    } 
    protected virtual bool OnLevel1IsValid() 
    {return true;} 
} 
public class Level2 : Level1 
{ 
    public string Data_Level2{get;set;} 

    protected override OnLevel1IsValid() 
    { 
     return Data_level2 != null; 
    } 
} 
+0

В чем отличие второго примера? Это выглядит немного более запутанным для меня. – 31eee384

+0

Это был долгий день - спасибо всем. – Softerware

ответ

1

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

public abstract class Employee : Person 
{ 
    public string Employer{get;set;} 

    protected override string OnSaySomething(string thoughts) 
    { 
     return base.OnSaySomething(thoughts)+ "I work for " + Employer + "."; 
    } 
} 

public class Engineer : Employee 
{ 
    public string Discipline{get;set;} 

    protected override string OnSaySomething(string thoughts) 
    { 
     return base.OnSaySomething(thoughts) + "My discipline is " + Discipline + "."; 
    } 
} 

EDIT: Используя обновленный код, он все еще то же самое

public class Level1 : Level0 
{ 
    public string Data_Level1{get;set;} 
    protected override bool OnIsValid() 
    { 
     return base.OnIsValid() && Data_level1 != null; 
    } 
} 
public class Level2 : Level1 
{ 
    public string Data_Level2{get;set;} 

    protected override OnLevel1IsValid() 
    { 
     return base.OnIsValid() && Data_level2 != null; 
    } 
} 

EDIT2: Для того, чтобы сделать это «Automatic» Вы в значительной степени была реализация уже сделано, одна дополнительная вещь, которую вы могли бы do - пометить свойства sealed, так что дальше по цепочке его нельзя переопределить, однако я бы не рекомендовал этот подход и вместо этого перешел с переопределениями в моем предыдущем примере.

public class Level1 : Level0 
{ 
    public string Data_Level1 { get; set; } 

    protected override sealed bool OnIsValid() 
    { 
     if (Data_Level1 == null) return false; 
     else return OnLevel1IsValid(); 
    } 

    protected virtual bool OnLevel1IsValid() 
    { 
     return true; 
    } 
} 

public class Level2 : Level1 
{ 
    public string Data_Level2 { get; set; } 

    protected override sealed bool OnLevel1IsValid() 
    { 
     return Data_Level2 != null; 
    } 
} 
1

Воспользоваться основание:

protected override string OnSaySomething(string thoughts) 
    { 

     return base.OnSaySomething() + thoughts + "My discipline is " + Discipline + "."; 
    } 
+0

Ваш синтаксис неверен, ваша сигнатура метода 'base.OnSaySomething()' не будет компилироваться. –

0

Я не совсем понимаю, что вы имеете в виду с «Я хочу продлить, не переопределять ", потому что вы, очевидно, используете ключевое слово" override ". В любом случае, я хотел бы предложить следующее решение:

public abstract class Person 
{ 
    public string Name{get;set;} 
    public virtual string SaySomething() 
    { 
     return = "Hello, my name is " + Name + ". "; 
    } 
} 

public abstract class Employee : Person 
{ 
    public string Employer{get;set;} 

    public override string SaySomething() 
    { 
     return base.SaySomething() + "I work for " + Employer + ". "; 
    } 
} 

public class Engineer : Employee 
{ 
    public string Discipline{get;set;} 

    public override string SaySomething() 
    { 
     return base.SaySomething() + "My discipline is " + Discipline + ". "; 
    } 
} 
+0

Мое предлагаемое решение также работает с вашим обновленным примером. Все, что вам нужно сделать, это заменить операцию строки логическими операциями AND, которые объединяют проверку класса под рукой с базовым классом. И, на мой взгляд, это самое простое решение из всех, потому что нет оснований делать всю диаграмму On ... (по крайней мере, вы не указали никаких дополнительных причин, которые могли бы задать этот более сложный шаблон дизайна). – Christoph

1

Вам необходимо позвонить в базовую версию.

protected override string OnSaySomething(string thoughts) 
{ 
     return base.OnSaySomething(thoughts) + "My discipline is " + Discipline + "."; 
} 
Смежные вопросы