theme changed
This commit is contained in:
350
labs/lab8/report.typ
Normal file
350
labs/lab8/report.typ
Normal file
@@ -0,0 +1,350 @@
|
||||
#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` и его реализация в целом являются хорошей основой для работы с книгами. Однако, для улучшения качества кода и его поддержки, необходимо внести изменения в стиль, структуру и обработку ошибок. Рекомендуется также рассмотреть возможность добавления тестов для проверки функциональности классов.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user