Files
oop/labs/lab8/report.typ
2025-09-30 08:21:09 +03:00

351 lines
12 KiB
Typst
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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` и его реализация в целом являются хорошей основой для работы с книгами. Однако, для улучшения качества кода и его поддержки, необходимо внести изменения в стиль, структуру и обработку ошибок. Рекомендуется также рассмотреть возможность добавления тестов для проверки функциональности классов.