Similar presentations:
Лабораторная_работа_№2_«Повторение_основных_принципов_ООП
1. Лабораторная работа №2 «Повторение основных принципов ООП» Тема квеста: «Система учёта сотрудников в небольшой компании»
Лабораторная работа №2 «Повторениеосновных принципов ООП»
Тема квеста:
«Система учёта сотрудников в небольшой
компании»
2. Легенда
Вы устроились на работу в небольшую компанию «Ромашка & К».В компании работает всего 10 человек, но директор устал вести учёт
зарплат в Excel. Он просит вас написать простую программу для учёта
сотрудников и их зарплат. В качестве благодарности он обещает
оплатить вам кофе на месяц вперёд.
Ваша задача: Создать консольное приложение, которое поможет
директору считать зарплату и вести список сотрудников.
3.
Этап 0: Подготовка (вводная)Директор дал вам такие вводные пояснения:
"У нас есть разные сотрудники: обычные работники, менеджеры и
директор. У всех есть имя и возраст. Зарплата считается по-разному.
Сделайте что-нибудь попроще, но чтобы работало. И да, в Excel
случайно удалил пару строк, так что пусть данные хранятся в
программе."
4.
Этап 1: Инкапсуляция (Класс Сотрудник)Задание: Создайте класс Sotrudnic (Сотрудник).
Поля:
_name (имя) — строка, не может быть пустой.
_age (возраст) — целое число, от 18 до 65.
_salary (зарплата) — вещественное число, не может быть отрицательным.
Требования:
Все поля должны быть private.
Для каждого поля сделайте свойства (getter/setter) с проверками:
o
Имя не может быть null или пустым.
o
Возраст от 18 до 65 включительно.
o
Зарплата >= 0.
Создайте конструктор, который принимает имя, возраст и зарплату.
Создайте метод GetInfo(), который возвращает строку с информацией о сотруднике
(например, "Иван, 25 лет, зарплата: 50000").
5.
Пример использования может быть таким:Sotrudnic emp = new Sotrudnic ("Иван", 25, 50000);
Console.WriteLine(emp.GetInfo());
// Попытка установить возраст 100 должна вызвать ошибку
// emp.Age = 100; // Ошибка!
6.
Этап 2: Наследование (Разные должности)Задание: Директор говорит, что у них есть три типа сотрудников:
1.Обычный сотрудник (Worker) — зарплата фиксированная (как в классе Sotrudnic).
2.Менеджер (Manager) — получает бонус 10% от своей зарплаты.
3.Директор (Director) — получает бонус 50% от зарплаты.
Создайте классы:
Worker — наследуется от Sotrudnic, ничего не меняет.
Manager — наследуется от Sotrudnic.
Director — наследуется от Sotrudnic.
Важно:
В классах Manager и Director переопределите метод GetInfo(), чтобы он показывал должность и
итоговую зарплату с бонусом.
Бонус должен считаться в отдельном методе CalculateSalary().
7.
Подсказка:public class Manager : Sotrudnic
{
public Manager(string name, int age, double salary)
: base(name, age, salary)
{
}
public double CalculateSalary()
{
return base.Salary * 1.1; // Базовая зарплата + 10%
}
public override string GetInfo()
{
return $"Менеджер: {Name}, возраст: {Age}, зарплата с бонусом: {CalculateSalary()}";
}
}
8.
Этап 3: Полиморфизм (Отдел кадров)Задание: Создайте класс HRDepartment (Отдел кадров).
1.
2.
3.
4.
У него должны быть:
Список всех сотрудников (List< Sotrudnic >).
Метод AddSotrudnic(Sotrudnic emp) — добавляет сотрудника в список.
Метод ShowAll Sotrudnics() — выводит информацию обо всех сотрудниках
(используя полиморфный вызов GetInfo()).
Метод CalculateTotalSalary() — считает общую сумму зарплат всех сотрудников с
учётом бонусов.
В методе CalculateTotalSalary() нельзя использовать if для проверки типа сотрудника.
Нужно сделать так, чтобы каждый сотрудник сам знал, как считать свою зарплату.
Для этого добавьте в базовый класс Sotrudnic виртуальный метод CalculateSalary(),
который просто возвращает Salary.
В классах Manager и Director переопределите этот метод.
9.
Пример:public class HRDepartment
{
private List< Sotrudnic > _sotrudnics = new List< Sotrudnic >();
public void AddSotrudnic(Sotrudnic emp)
{
_sotrudnics.Add(emp);
}
public void ShowAllSotrudnics()
{
foreach (var emp in _sotrudnics)
{
Console.WriteLine(emp.GetInfo());
}
}
public double CalculateTotalSalary()
{
double total = 0;
foreach (var emp in _sotrudnics)
{
total += emp.CalculateSalary(); // Полиморфный вызов!
}
return total;
}
}
10.
Этап 4: Абстракция (Контрактники и Штатные)Задание: Директор вспомнил, что у них есть ещё и внештатные сотрудники (фрилансеры),
которые работают по часам. Их тоже нужно учитывать, но у них нет фиксированной зарплаты.
Создайте интерфейс ISotrudnic:
public interface ISotrudnic
{
string GetInfo();
double CalculateSalary();
}
Теперь:
1. Класс Sotrudnic должен реализовать интерфейс ISotrudnic (просто допишите: ISotrudnic).
2. Создайте новый класс Freelancer (Внештатник), который не наследуется от Sotrudnic, а просто
реализует интерфейс ISotrudnic.
У фрилансера есть Name и HourlyRate (ставка в час).
Зарплата считается как HourlyRate * HoursWorked (количество отработанных часов
передавайте в метод).
11.
public class Freelancer : ISotrudnic{
public string Name { get; set; }
public double HourlyRate { get; set; }
private int _hoursWorked;
public Freelancer(string name, double rate)
{
Name = name;
HourlyRate = rate;
}
public void AddHours(int hours)
{
_hoursWorked += hours;
}
public double CalculateSalary()
{
return HourlyRate * _hoursWorked;
}
public string GetInfo()
{
return $"Фрилансер: {Name}, отработано часов: {_hoursWorked}, зарплата: {CalculateSalary()}";
}
}
12.
Финальное задание:Измените HRDepartment так, чтобы он работал с List<ISotrudnic>, а не
List< Sotrudnic >. Теперь он может хранить и обычных сотрудников, и
фрилансеров.
13.
Чек-лист для самопроверкиБазовый уровень (на 3):
Класс Sotrudnic с приватными полями и свойствами.
Проверки в сеттерах (имя не пустое, возраст 18-65, зарплата >= 0).
Конструктор.
Средний уровень (на 4):
Классы Manager и Director с переопределённым методом CalculateSalary().
Класс HRDepartment с методом CalculateTotalSalary() без if.
Полиморфный вызов GetInfo().
Хороший уровень (на 5):
Интерфейс ISotrudnic.
Класс Freelancer, реализующий интерфейс.
HRDepartment работает с List<ISotrudnic >.
Все типы сотрудников корректно отображаются и считают зарплату.
14.
ПодсказкиЕсли не работает:
Не забывайте про base в конструкторах наследников.
Для переопределения методов используйте virtual в базовом классе и override в наследниках.
Свойства можно сделать авто-свойствами, если не нужна сложная логика, но проверки всё
равно нужны.
Для проверки возраста можно использовать:
set
{
if (value < 18 || value > 65)
throw new ArgumentException("Возраст должен быть от 18 до 65");
_age = value;
}