# Задание на лабораторную работу

{% hint style="warning" %}
В данной лабораторной работе задания выполняются с помощью плагина EduTools!

При решении задачи сначала добавьте сигнатуру методов и возвращаемые значения для того, чтобы тесты могли скомпилироваться корректно!
{% endhint %}

{% file src="<https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-MHtw_J5S8YROp21AdhM%2F-MHuLW0HJqWt3xWSBQ2S%2FJava_inheritance.zip?alt=media&token=72200517-fe99-433c-8423-56aac2bb5aa7>" %}
Java Inheritance lab work 4
{% endfile %}

{% hint style="warning" %}
Реализуйте каждую задачу с помощью механизма наследования, а потом - с помощью механизма композиции.

Для каждой реализации нарисуйте UML-диаграмму классов. Вы можете нарисовать одну диаграмму для двух заданий, реализованных с помощью наследования и одну диаграмму для заданий, реализованных с помощью механизма наследования.
{% endhint %}

### 1. Класс Point3D

Дан класс `Point`, который моделирует точку в двумерном пространстве. Класс включает в себя следующие конструкторы и публичные методы:

| Сигнатура                               | Описание                                                                                                                                                               |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `public Point()`                        | Создает точку с координатами `(0, 0)`                                                                                                                                  |
| `public Point(int x, int y)`            | Создает точку с координатами `(x, y)`                                                                                                                                  |
| `public void setLocation(int x, int y)` | Устанавливает новые координаты точки                                                                                                                                   |
| `public int getX()`                     | Возвращает значение координаты X                                                                                                                                       |
| `public int getY()`                     | Возвращает значение координаты Y                                                                                                                                       |
| `public String toString()`              | Возвращает строку в виде `"(x,y)"`                                                                                                                                     |
| `public int distanceFromOrigin()`       | <p>Возвращает расстояние от начала координат (0, 0)<br>до точки по формуле <br>расстояния Евклида <span class="math"> \sqrt{(x\_1-x\_2)^2 + (y\_1-y\_2)^2}</span> </p> |

Создайте класс `Point3D`, который расширяет класс Point через наследование. Он должен вести себя как `Point`, за исключением того что это должна быть точка в трехмерном пространстве, которая хранит значение координаты `Z`.&#x20;

Вы должны предоставить те же методы, что и суперкласс, а также реализовать дополнительное поведение

| Сигнатура                                      | Описание                                 |
| ---------------------------------------------- | ---------------------------------------- |
| `public Point3D()`                             | Создает точку с координатами `(0, 0, 0)` |
| `public Point3D(int x, int y, int z)`          | Создает точку с координатами `(x, y, z)` |
| `public void setLocation(int x, int y, int z)` | Устанавливает новые координаты           |
| `public int getZ()`                            | Возвращает координату `Z`                |

Класс `Point3D()` должен переопределить требуемые методы, чтобы они работали корректно с учетом третьей координаты. Также класс `Point3D` должен вести себя иначе в следующих ситуациях:

* при вызове метода `setLocation(int x, int y)`, координата `z` должна быть выставлена в 0;
* при вызове метода `toString()`, строка должна выводить три координаты, а не две;
* метод `distanceFromOrigin()` должны учитывать координату z и возвращать расстояние по формуле $$\sqrt{(x\_1-x\_2)^2 + (y\_1-y\_2)^2 + (z\_1-z\_2)^2}$$ .

### 2. Класс DiscountBill

Дан класс `GroceryBill`, который моделирует чек и хранит список товаров, который покупает человек в супермаркете. Класс включает в себя следующие конструкторы и публичные методы:

| Сигнатура                            | Описание                                         |
| ------------------------------------ | ------------------------------------------------ |
| `public GroceryBill(Employee clerk)` | Создает объект `GroceryBill` для данного `clerk` |
| `public void add(Item i)`            | Добавляет товар в чек                            |
| `public double getTotal()`           | Возвращает итоговую стоимость товаров            |
| `public void printReceipt()`         | Распечатывает список товаров                     |

Объект `GroceryBill` взаимодействует с объектами класса `Item`. Класс `Item` включает следующие публичные методы:

| Сигнатура                     | Описание                           |
| ----------------------------- | ---------------------------------- |
| `public double getPrice()`    | Возвращает стоимость товара        |
| `public double getDiscount()` | Возвращает скидку для этого товара |

К примеру, товар стоит 1.35, а размер скидки 0.25 для постоянных покупателей. Это означает, что постоянный покупатель должен заплатить 1.10. **Некоторые товары могут не иметь скидки (размер скидки 0.0)**. В классе `GroceryBill` не предусмотрена логика для учета скидки, то есть учитывается только полная стоимость товара.

Разработайте класс `DiscountBill`, который расширяет класс `GroceryBill` и добавляет логику для учета скидки для постоянных клиентов. Конструктор класс `DiscountBill` должен принимать на вход параметр, который указывает, является ли клиент постоянным.

Класс `DiscountBill` должен реализовывать собственную логику метода `getTotal()` для постоянных покупателей. Например, если полная сумма равна 80 гривен, а скидка для постоянного клиента составила 20 гривен, метод должен возвращать 60 гривен.

Также, вам необходимо отслеживать количество товаров со скидкой (у которых размер скидки больше 0.0), а также общую скидку, как в гривнах, так и в процентах от суммы в чеке (то есть, насколько в процентах постоянный покупатель заплатил меньше, чем если бы скидки не было).&#x20;

Помимо переопределенных методов, класс `DiscountBill` должен иметь следующие конструкторы и публичные методы:

| Сигнатура                                                                                         | Описание                                                                                             |
| ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| <p><code>public DiscountBill</code><br><code>(Employee clerk, boolean regularCustomer)</code></p> | Создает объект `DiscountBill` для данного `clerk`                                                    |
| `public int getDiscountCount()`                                                                   | Возвращает количество товаров со скидкой                                                             |
| `public double getDiscountAmount()`                                                               | Возвращает общую скидку в гривнах                                                                    |
| `public double getDiscountPercent()`                                                              | <p>Возвращает процент скидки для товаров<br>(на сколько процентов покупатель<br>заплатил меньше)</p> |

Если покупатель не является регулярным, класс `DiscountBill` должен вести себя как будто общая скидка равна 0 и все товары учтены по их полной стоимости.
