Вложенные базовые классы в c # - PullRequest
4 голосов
/ 24 июня 2010

У меня есть 3 класса, два наследуют от 1:

public class Employee {
    private virtual double getBonus() { ... }
    private virtual double getSalary() { ... }
}

public class Nepotism : Employee {
    private double getBonus() { ... }
}

public class Volunteer : Employee {
    private double getSalary() { ... }
}

Так что вопрос в том, что иногда найдется Волонтер, который получит бонус за непотизм - есть ли какой-то способ написать конструкторы, позволяющие переопределитьвложив класс base следующим образом:

Employee Bill = new Volunteer(new Nepotism());

Я думаю что-то вроде:

public class Volunteer : Employee {
    private Employee _nest;
    public Volunteer(Employee nest) 
        : base() {
        _nest = nest;
        // now what?
    }
}

В основном я хочу, чтобы некоторые объекты имели переопределения из обоих классов.

Я бы хотел избегать написания методов переопределения для проверки на наличие вложенных классов.

getSalary() {
    return (nest != null) ? nest.salary : salary; // I want to avoid this if I can
}

Как я могу это сделать?Я на правильном пути?Я сошел с рельсов?

Ответы [ 4 ]

13 голосов
/ 24 июня 2010

Вместо создания подклассов вы можете рассмотреть возможность использования Pattern Decorator .

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

4 голосов
/ 24 июня 2010

Я думаю, что вы пытаетесь использовать наследование опрометчивым образом.Этот подход создает беспорядок зависимостей и странных бизнес-правил, что приводит к жесткой архитектуре, которую сложно использовать и поддерживать.

Если расчет заработной платы сотрудника зависит от сотрудника, а также от «бонусных черт», то было бы лучше отделить все три вещи друг от друга:

interface IBonusTrait
{
    decimal ApplyBonus(Employee employee, decimal currentTotal);
}

class Employee
{
    // ...

    public decimal BaseSalary { get; set; }
    public IList<IBonusTrait> BonusTraits { get; set; }
}

class SalaryCalculator
{
    public decimal CalculateSalary(Employee employee)
    {
        decimal totalSalary = employee.BaseSalary;
        foreach (IBonusTrait bonusTrait in employee.BonusTraits)
        {
            totalSalary = bonusTrait.ApplyBonus(employee, totalSalary);
        }

        return totalSalary;
    }
}
0 голосов
/ 11 марта 2014

Рид Копси уже сказал, что Pattern Decorator - это то, что нужно учитывать.

Существует также видео на YouTube , которое очень похоже на ваш случай (Джон Скит представляет его).

0 голосов
/ 24 июня 2010

Если объект может быть одновременно обоими классами, то вам, возможно, придется переосмыслить, как вы делаете наследование.

Мне кажется, что если Волонтер иногда может получить бонус Непотизма, тогда действительно, у вашего волонтерского класса должен быть метод getBonus (), и этот метод действительно принадлежит базовому классу. Для большинства добровольцев он вернет ноль, но иногда это не будет - в этом нет ничего плохого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...