#set text(size: 1.3em)

#show raw.where(block: false): box.with(
  fill: luma(240),
  inset: (x: 3pt, y: 0pt),
  outset: (y: 3pt),
  radius: 2pt,
)

#show raw.where(block: true): block.with(
  fill: luma(240),
  inset: 10pt,
  radius: 4pt,
)
    
// title
    
#align(center)[Санкт-Петербургский национальный исследовательский университет информационных технологий, механики и оптики]
\
\
\
#align(center)[Факультет инфокоммуникационных технологий]
#align(center)[Направление подготовки 11.03.02]
\
\
#align(center)[Лабораторная работа №8]
#align(center)[Использование интерфейсов при реализации иерархии классов]
\
\
\ //#align(center)[Вариант 19]
\
\
\
\
\
\
\
#align(right)[Выполнил:]
#align(right)[Дощенников Никита Андреевич]
#align(right)[Группа: К3221]
#align(right)[Проверил:]
#align(right)[Иванов Сергей Евгеньевич]
\
\
#align(center)[Санкт-Петербург]
#align(center)[2025]

#pagebreak()
    
=== Цель работы:

Использовать интерфейсы при реализации иерархии классов как важного элемента объектно-ориентированного программирования и приобретение навыков реализации интерфейсов.

=== Упражнение 1. Создание и реализация интерфейса.

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

```cs
using System;

interface IPubs
{
    void Subs();
    bool IfSubs { get; set; }
}
```

```cs
using System;

class Magazine : Item, IPubs
{
    private String volume;
    private int number;
    private String title;
    private int year;

    public Magazine(String volume, int number, String title, int year, long invNumber, bool taken) : base(invNumber, taken)
    {
        this.volume = volume;
        this.number = number;
        this.title = title;
        this.year = year;
    }

    public Magazine()
    {}

    public override void Show()
    {
        Console.WriteLine("\nЖурнал:\n Том: {0}\n Номер: {1}\n Название: {2}\n Год выпуска: {3}", volume, number, title, year);
        base.Show();
    }


    public override void Return()
    {
        taken = true;
    }

    public bool IfSubs { get; set; }

    public void Subs()
    {
        Console.WriteLine("Подписка на журнал \"{0}\": {1}.", title, IfSubs);
    }

}
```

Тесты: 

```cs
public static void Main(string[] args)
{
    Magazine mag1 = new Magazine("О природе", 5, "Земля и мы", 2014, 1235, true);
    mag1.TakeItem();
    mag1.Show();
    mag1.IfSubs = true;
    mag1.Subs();
}
```

Пример: 

#align(center)[#image("assets/1.png")]

=== Упражнение 2. Использование стандартных интерфейсов.

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

```cs
using System; 

abstract class Item : IComparable
{
    protected long invNumber;
    protected bool taken;

    public Item(long invNumber, bool taken)
    {
        this.invNumber = invNumber;
        this.taken = taken;
    }

    public Item()
    {
        this.taken = true;
    }

    public bool IsAvailable()
    {
        return taken;
    }

    public long GetInvNumber()
    {
        return invNumber;
    }

    private void Take()
    {
        taken = false;
    }

    public void TakeItem()
    {
        if (this.IsAvailable())
            this.Take();
    }


    abstract public void Return();

    public virtual void Show()
    {
        Console.WriteLine("Состояние единицы хранения:\n Инвентарный номер: {0}\n Наличие: {1}", invNumber, taken);
    }

    int IComparable.CompareTo(object obj)
    {
        Item it = (Item)obj;
        if (this.invNumber == it.invNumber) return 0;
        else if (this.invNumber > it.invNumber) return 1;
        else return -1;
    }
}
```

Тесты:

```cs
public static void Main(string[] args)
{
    Item[] items = new Item[4];
    items[0] = b1;
    items[1] = b2;
    items[2] = b3;
    items[3] = mag1;

    Array.Sort(items);

    Console.WriteLine("\nСортировка по инвентарному номеру");
    foreach (Item x in items)
    {
        x.Show();
    }
}
```

Пример: 

#align(center)[#image("assets/2.png")]

=== Упражнение 3. Реализация прогрессии с помощью интерфейса.

В этом упражнении я заменил абстрактный класс `Progression` на интерфейс `IProgression`, определяющий поведение классов `ArithmeticProgression` и `GeometricProgression`, описывающих арифметическую и геометрическую прогрессии.

```cs
using System;

interface IProgression
{
    int GetElement(int k);
    int Sum(int n);
}
```

```cs
using System;

class ArithmeticProgression : IProgression
{
    private int a0;
    private int b;

    public ArithmeticProgression(int a0, int b)
    {
        this.a0 = a0;
        this.b = b;
    }

    public int GetElement(int k)
    {
        return a0 + (k - 1) * b;
    }

    public int Sum(int n)
    {
        return (2 * a0 + (n - 1) * b) * n / 2;
    }
}
```

```cs
using System;

class GeometricProgression : IProgression
{
    private int p0;
    private int q;

    public GeometricProgression(int p0, int q)
    {
        this.p0 = p0;
        this.q = q;
    }

    public int GetElement(int k)
    {
        return p0 * (int)Math.Pow(q, k - 1);
    }

    public int Sum(int n)
    {
        if (q == 1) return p0 * n;
        return p0 * (int)((Math.Pow(q, n) - 1) / (q - 1));
    }
}
```

Тесты: 

```cs
public static void Main(string[] args)
{
    IProgression arith = new ArithmeticProgression(2, 3);
    IProgression geom = new GeometricProgression(2, 2);

    Console.WriteLine("Арифметическая прогрессия:");
    Console.WriteLine("5-й элемент = " + arith.GetElement(5));
    Console.WriteLine("Сумма 5 элементов = " + arith.Sum(5));

    Console.WriteLine("\nГеометрическая прогрессия:");
    Console.WriteLine("5-й элемент = " + geom.GetElement(5));
    Console.WriteLine("Сумма 5 элементов = " + geom.Sum(5));
}
```

Пример: 

#align(center)[#image("assets/3.png")]

=== Выводы.

В ходе проделанной лабораторной работы я использовал интерфейсы при реализации иерархии классов как важного элемента объектно-ориентированного программирования и приобретел навыки реализации интерфейсов.

=== Code review. (by #link("https://zzzcode.ai")[zzzcode.ai])

*Резюме*

Класс `Book` представляет собой реализацию книги с различными атрибутами, такими как автор, название, издатель и т.д. Он наследуется от абстрактного класса `Item`, который управляет состоянием доступности книги. Код в целом хорошо структурирован, но требует некоторых улучшений в области стиля и производительности.

*Ошибка*

В методе `Return()` класса `Book` переменная `taken` устанавливается в значение `returnSrok`, которое по умолчанию равно `false`. Это может привести к тому, что книга будет считаться возвращенной, даже если она не была возвращена. Следует добавить логику для проверки состояния возврата.

*Стиль кода*

Использование `String` вместо `string` не соответствует общепринятому стилю C\#. Рекомендуется использовать `string` (с маленькой буквы). Имена переменных и методов должны следовать соглашениям о наименовании. Например, `returnSrok` можно переименовать в `isReturned` для большей ясности.

*Структура кода*

Класс `Book` имеет хорошую структуру, однако: Конструкторы перегружены, что может усложнить создание объектов. Рекомендуется использовать один конструктор с параметрами по умолчанию. Метод `SetBook` можно заменить на использование свойств, что улучшит инкапсуляцию.

*Читаемость*

Код читаем, но можно улучшить: Добавить XML-комментарии к методам и классам для лучшего понимания их назначения. Разделить длинные строки на несколько строк для повышения читаемости.

*Производительность*

Статическая переменная `price` может быть изменена через метод `SetPrice`, что может привести к неожиданным изменениям. Рекомендуется сделать её свойством только для чтения или использовать паттерн Singleton для управления ценой.

*Масштабируемость*

Класс `Book` может быть расширен для поддержки дополнительных атрибутов, таких как жанр или ISBN. Однако, если количество атрибутов увеличится, стоит рассмотреть возможность использования паттерна проектирования, такого как `Builder`.

*Безопасность*

Необходимо добавить валидацию входных данных в конструкторах и методах, чтобы предотвратить создание объектов с некорректными значениями (например, отрицательное количество страниц или год).

*Обработка ошибок*

В текущем коде отсутствует обработка исключений. Рекомендуется добавить обработку ошибок, особенно в методах, которые могут вызывать исключения, таких как `PriceBook`.

*Заключение*

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


