Путаница в отношении наследования на основе примеров - PullRequest
1 голос
/ 12 июня 2019

Иногда меня часто путают между тем, когда выводить класс (использовать наследование), а когда нет. Так, например, у меня есть такой код:

public class Payroll
{
    public void ProcessPayroll(Employee e) //abstraction
    {
         e.ProcessPayroll();
    }
}

Class Employee : Payroll
{
    public virtual void ProcessPayroll()
    {
       //Process Payroll
    }
}

class FulltimeEmployee : Employee
{
    public override void ProcessPayroll()
    {
       //Payroll processing based on fulltime employee
    }
}

Это имеет смысл:

class FulltimeEmployee : Employee

Becuase FulltimeEmployee is a Employee, поэтому IS-A relationship здесь справедливо.

Но я запутался здесь из-за отношений ниже, так как это наследство имеет смысл, поскольку оно не "IS-A" relationship?

Class Employee : Payroll

Кроме того, наследование всегда должно следовать отношениям IS-A?

Другой пример:

Требование гласит: «Сотрудник не может существовать без Компании»

На основании этого я сделал это:

public class Company

public class Employee : Company

Теперь это имеет смысл?

Обновление:

Я думаю, что выше можно лучше представить, используя Aggregation:

public class Company
{ 
    Employee E; //because Company has-a Employee
}

Но завтра, если требование говорит Компания может существовать и без Employee , что означает, что я должен прийти в этот класс и обновить код.

Разве это не нарушит Open and Closed principle?

Ответы [ 2 ]

3 голосов
/ 12 июня 2019

Требование гласит: «Сотрудник не может существовать без Компании», это означает, что в компании есть сотрудники.Отношения Has-A также известны как композиция.Вам не нужен этот класс Сотрудник: Заработная плата.Это должен быть просто класс Employee.

В классе Payroll объект Employee внедряется, поэтому он может обрабатываться мгновенными методами.Также для хорошей практики следуйте этому Предпочитать состав перед наследованием?

Ответ для обновленной части: принцип Open open говорит: "Класс открыт для расширения, но закрыт для модификации"

public class Company
    {
        private readonly IEmployee e;
        public Company(IEmployee e)
        {
            this.e = e;
        }
    }
    public interface IEmployee
    { //Some employee related methods
    }

Здесь вы ввели IEmployee в классе компании.Теперь вы можете расширить функциональность корпоративного класса, используя мгновенную версию IEmployee.Посмотрите на пример паттерна стратегии, который, надеюсь, прояснил ваши сомнения Пример паттерна стратегии в реальном мире

1 голос
/ 12 июня 2019

То, что вы говорите, это скорее отношения HAS-A, поэтому вам нужна композиция:

public class Employee
{
  Payroll payroll;
  Company company;
  ...
}

Так как каждый сотрудник где-то нанят, значит, у него есть компания, в которой он работает.

С другой стороны, у компании есть сотрудники, поэтому она может быть спроектирована так же, как:

public class Company
{
  List<Employee> employees;
  ...
}

Вам нужно подготовить себя также к ситуации, когда Employee не имеет Company или наоборот, тогда соответствующие поля в классах будут null, учитывая, что вам нужно написать свои методы с проверками null для справиться с такой ситуацией, как:

if(employees == null || employeses.Count == 0)
  Console.WriteLine("Sorry, company has no employees!");
...