This commit is contained in:
nik
2025-09-30 14:26:54 +03:00
parent 8bd93df2ae
commit 8164e04835
633 changed files with 8 additions and 8 deletions

600
labs/lab7_done/report.typ Normal file
View File

@@ -0,0 +1,600 @@
#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)[Лабораторная работа №7]
#align(center)[Создание иерархии классов]
\
\
\ //#align(center)[Вариант 19]
\
\
\
\
\
\
\
#align(right)[Выполнил:]
#align(right)[Дощенников Никита Андреевич]
#align(right)[Группа: К3221]
#align(right)[Проверил:]
#align(right)[Иванов Сергей Евгеньевич]
\
\
#align(center)[Санкт-Петербург]
#align(center)[2025]
#pagebreak()
=== Цель работы:
Изучение наследования как важного элемента объектно-ориентированного программирования и приобретение навыков реализации иерархии классов.
=== Упражнение 1. Реализация наследования классов.
В этом упражнении я использовал наследование для построения иерархии между классами, имеющих отношение типа "является". Вы добавите новый класс `Item`, который будет являться базовым для уже имеющегося класса `Book`.
```cs
using System;
abstract class Item
{
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);
}
}
```
```cs
using System;
class Book : Item
{
private String author;
private String title;
private String publisher;
private int pages;
private int year;
private bool returnSrok;
private static double price = 9;
static Book()
{
price = 10;
}
public Book()
{
}
public Book(String author, String title, String publisher, int pages, int year, long invNumber, bool taken) : base (invNumber, taken)
{
this.author = author;
this.title = title;
this.publisher = publisher;
this.pages = pages;
this.year = year;
}
public Book(String author, String title)
{
this.author = author;
this.title = title;
}
public void SetBook(String author, String title, String publisher, int pages, int year)
{
this.author = author;
this.title = title;
this.publisher = publisher;
this.pages = pages;
this.year = year;
}
public static void SetPrice(double price)
{
Book.price = price;
}
public override void Show()
{
Console.WriteLine("\nКнига:\n Автор: {0}\n Название: {1}\n Год издания: {2}\n {3} стр.\n Стоимость аренды: {4}", author, title, year, pages, Book.price);
base.Show();
}
public double PriceBook(int s)
{
double cost = s * price;
return cost;
}
public void ReturnSrok()
{
returnSrok = true;
}
public override void Return()
{
taken = returnSrok;
}
}
```
Тесты:
```cs
public static void Main(string[] args)
{
Item item1 = new Item();
item1.Show();
}
```
=== Упражнение 2. Использование конструкторов.
В этом упражнении я определил конструкторы в базовом и в производном классах и реализуете их выполнение в обоих классах с помощью ключевого слова `base`, которое позволяет вызвать конструктор базового класса.
```cs
using System;
class Magazine : Item
{
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;
}
}
```
Тесты:
```cs
public static void Main(string[] args)
{
Book b2 = new Book("Толстой Л. Н.", "Война и мир", "Наука и жизнь", 1234, 2013, 101, true);
b2.Show();
b2.TakeItem();
b2.Show();
Magazine mag1 = new Magazine("О природе", 5, "Земля и мы", 2014, 1235, true);
mag1.Show();
}
```
Пример:
#align(center)[#image("assets/1.png")]
=== Упражнение 3. Переопределение методов.
В этом упражнении я реализовал механизм полиморфизма с помощью виртуальных методов и их переопределения в производных классах.
```cs
public static void Main(string[] args)
{
Book b2 = new Book("Толстой Л. Н.", "Война и мир", "Наука и жизнь", 1234, 2013, 101, true);
b2.Show();
b2.TakeItem();
b2.Show();
Magazine mag1 = new Magazine("О природе", 5, "Земля и мы", 2014, 1235, true);
mag1.Show();
Console.WriteLine("\n Тестирование полиформизма");
Item it;
it = b2;
it.TakeItem();
it.Return();
it.Show();
it = mag1;
it.TakeItem();
it.Return();
it.Show();
}
```
Пример:
#align(center)[#image("assets/2.png")]
=== Упражнение 4. Применение абстрактного класса и абстрактных методов.
В этом упражнении я сделал базовый класс и один из его методов абстрактным.
Тесты и примеры совпадают с предыдущим упражнением.
=== Упражнение 5. Реализации модели включения.
В этом упражнении я реализовал отношение "имеет", известное под названием модели включения или агрегации.
```cs
using System;
class Point
{
private double x;
private double y;
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
public Point ()
{}
public void Show()
{
Console.WriteLine("Точка с координатами: ({0}, {1})", x, y);
}
public double Dlina(Point p)
{
double Dl = Math.Sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y));
return Dl;
}
public override string ToString()
{
string ss = x + " ; " + y;
return ss;
}
}
```
```cs
using System;
class Line
{
private Point pStart;
private Point pEnd;
public Line(Point pStart, Point pEnd)
{
this.pStart = pStart;
this.pEnd = pEnd;
}
public Line()
{ }
public void Show()
{
Console.WriteLine("Отрезок с координатами: ({0}) - ({1})", pStart, pEnd);
}
public double DlinL()
{
return pStart.Dlina(pEnd);
}
}
```
Тесты:
```cs
using System;
public class Program
{
public static void Main(string[] args)
{
Point p1 = new Point();
p1.Show();
Point p2 = new Point(12, 13);
p2.Show();
Line line = new Line(p1, p2);
line.Show();
double dtr = line.DlinL();
Console.WriteLine("Длина отрезка " + dtr);
}
}
```
Примеры:
#align(center)[#image("assets/3.png")]
=== Упражнение 6. Реализация отношения ассоциации между классами.
В этом упражнении я создал класс, моделирующий игральную кость и класс игрока, который связан с классом игры отношением ассоциации - каждый отдельный сеанс игры связан с конкретным игроком, бросающим кубик.
```cs
using System;
class IgralnayaKost
{
Random r;
public IgralnayaKost()
{
r = new Random();
}
public int random()
{
int res = r.Next(6) + 1;
return res;
}
}
```
```cs
using System;
class Gamer
{
string Name;
IgralnayaKost seans;
public Gamer(string name)
{
Name = name;
seans = new IgralnayaKost();
}
public int SeansGame()
{
return seans.random();
}
public override string ToString()
{
return Name;
}
}
```
Тесты:
```cs
public static void Main(string[] args)
{
Gamer g1 = new Gamer("Niko");
for (int i = 1; i <= 6; i++)
{
Console.WriteLine("Выпало количество очков {0} для игрока {1}", g1.SeansGame(), g1.ToString());
}
}
```
Примеры:
#align(center)[#image("assets/4.png")]
=== Упражнение 7. Реализация прогрессии.
В этом упражнении я определил абстрактный класс `Progression`, описывающий прогрессии. В этом классе определил абстрактный метод `GetElement` с целочисленным параметром `k`, возвращающий элемент прогрессии. Определил два производных класса `ArithmeticProgression` и `GeometricProgression`, описывающие арифметическую и геометрическую прогрессии. В каждом из классов определил конструктор, задающий параметры прогрессии и перегрузил унаследованный метод `GetElement`.
```cs
using System;
abstract class Progression
{
public abstract int GetElement(int k);
public abstract int Sum(int n);
}
```
```cs
using System;
class ArithmeticProgression : Progression
{
private int a0;
private int b;
public ArithmeticProgression(int a0, int b)
{
this.a0 = a0;
this.b = b;
}
public override int GetElement(int k)
{
return a0 + (k - 1) * b;
}
public override int Sum(int n)
{
return (2 * a0 + (n - 1) * b) * n / 2;
}
}
```
```cs
using System;
class GeometricProgression : Progression
{
private int p0;
private int q;
public GeometricProgression(int p0, int q)
{
this.p0 = p0;
this.q = q;
}
public override int GetElement(int k)
{
return p0 * (int)Math.Pow(q, k - 1);
}
public override 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)
{
Progression arith = new ArithmeticProgression(2, 3);
Progression 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/5.png")]
=== Выводы.
В ходе проделанной работе я изучил наследование как важный элемент объектно-ориентированного программирования и приобрел навыки реализации иерархии классов.
=== Code review. (by #link("https://zzzcode.ai")[zzzcode.ai])
*Резюме*
Код представляет собой реализацию нескольких классов, включая `Gamer`, `Book`, `Magazine`, `Item`, `Triangle`, `Line`, `Point`, и прогрессии. Основная логика кода заключается в моделировании игровых сессий и библиотечных предметов. Однако, код требует улучшений в области стиля, структуры и обработки ошибок.
*Ошибка*
В классе `Gamer` отсутствует проверка на `null` для параметра `name` в конструкторе. Это может привести к исключению, если передать `null`. Также метод `random()` в классе `IgralnayaKost` не определен в предоставленном коде, что может вызвать ошибки компиляции.
*Стиль кода*
Имена переменных и методов должны следовать соглашениям о наименовании C\#. Например, `Name` и `seans` следует переименовать в `name` и `session` соответственно. Рекомендуется использовать свойства вместо полей для обеспечения инкапсуляции.
*Структура кода*
Код разбит на несколько классов, что хорошо для организации. Однако, стоит рассмотреть возможность разделения на отдельные файлы для каждого класса, чтобы улучшить читаемость и поддержку.
*Читаемость*
Код в целом читаем, но использование комментариев и документации для методов и классов значительно улучшит понимание кода другими разработчиками.
*Производительность*
Код не содержит явных проблем с производительностью, однако использование статических методов и свойств может быть оптимизировано для уменьшения потребления памяти.
*Масштабируемость*
Код может быть расширен, но для этого потребуется более четкая архитектура. Например, использование интерфейсов для классов `Item`, `Book`, и `Magazine` может улучшить гибкость и масштабируемость.
*Безопасность*
Отсутствие проверки входных данных может привести к уязвимостям. Рекомендуется добавить валидацию для всех входных параметров, особенно в конструкторах.
*Обработка ошибок*
Код не содержит механизма обработки ошибок. Рекомендуется использовать конструкции `try-catch` для обработки возможных исключений, особенно в методах, которые могут вызывать ошибки, такие как `random()`.
*Заключение*
Код демонстрирует базовые принципы объектно-ориентированного программирования, но требует улучшений в области стиля, структуры и обработки ошибок. Рекомендуется провести рефакторинг для повышения читаемости и безопасности, а также добавить документацию для улучшения поддержки кода в будущем.