> For the complete documentation index, see [llms.txt](https://axideli.gitbook.io/osnovy-programmirovaniya-na-yazyke-c/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://axideli.gitbook.io/osnovy-programmirovaniya-na-yazyke-c/obektno-orientirovannoe-programmirovanie.md).

# Объектно-ориентированное программирование

## Введение в объектно-ориентированное программирование (ООП)

#### **Определение ООП и его основные принципы**

**Объектно-ориентированное программирование (ООП)** представляет собой методологию разработки программного обеспечения, основанную на использовании объектов, которые включают данные и методы для их обработки. ООП стремится моделировать реальные объекты и их взаимодействие, что упрощает процесс разработки и обслуживания кода.

*Основные принципы ООП:*

* **Классы и объекты:** Класс представляет собой шаблон для создания объектов. Объект - это экземпляр класса, обладающий определенными свойствами и методами.
* **Наследование:** Механизм, позволяющий создавать новый класс на основе существующего, наследуя его свойства и методы. Это обеспечивает повторное использование кода и иерархию классов.
* **Инкапсуляция:** Принцип, заключающийся в объединении данных и методов, работающих с этими данными, в единый объект. Инкапсуляция скрывает детали реализации и обеспечивает контролируемый доступ.
* **Полиморфизм:** Возможность объектов с одинаковой спецификацией использовать их по-разному. Это может быть достигнуто через перегрузку методов, интерфейсы и абстрактные классы.

#### **Значение и преимущества ООП в разработке программного обеспечения**

**Значение ООП:**

* **Моделирование реального мира:** ООП позволяет разработчикам создавать программы, более точно отражающие структуры и взаимодействия объектов в реальном мире.
* **Повторное использование кода:** Классы и объекты могут быть повторно использованы в различных частях программы или даже в разных проектах, что экономит время и ресурсы.
* **Упрощение сопровождения:** Код на основе ООП обычно легче понимать, изменять и расширять. Изменения в одной части программы могут оказаться минимальными для других частей.

**Преимущества ООП:**

* **Разделение ответственности:** ООП способствует разделению кода на небольшие, самодостаточные блоки (классы), что упрощает поддержку и разработку.
* **Инкапсуляция и контролируемый доступ:** Инкапсуляция обеспечивает скрытие деталей реализации, что способствует контролируемому и безопасному доступу к данным.
* **Повышение повторного использования кода:** Механизмы наследования и композиции в ООП позволяют повторно использовать код, уменьшая дублирование.

#### **Основные понятия: классы, объекты, наследование, инкапсуляция, полиморфизм**

**Основные понятия:**

* **Классы:** Абстракция, представляющая собой шаблон для создания объектов. Класс определяет свойства (поля) и методы, которые будут присутствовать у объектов.
* **Объекты:** Экземпляры классов, обладающие конкретными значениями свойств и возможностью вызова методов.
* **Наследование:** Механизм, позволяющий новым классам использовать свойства и методы существующих классов, способствуя повторному использованию кода.
* **Инкапсуляция:** Упаковка данных и методов, работающих с ними, в единый объект (класс), предоставляя контролируемый доступ и скрывая детали реализации.
* **Полиморфизм:** Возможность объектов использовать методы с одинаковой сигнатурой по-разному. Это может быть достигнуто через перегрузку методов, интерфейсы и абстрактные классы.

## Классы и объекты в C\#

#### **Определение классов и создание объектов**

**Определение классов:**

Класс в C# - это шаблон или тип данных, который определяет свойства и методы объекта. Он предоставляет описание того, как создать объект этого класса. Класс определяет атрибуты и поведение, которые будут унаследованы объектами этого класса.

```csharp
csharpCopy codepublic class Car
{
    // Поля класса
    public string Model;
    public int Year;

    // Метод класса
    public void StartEngine()
    {
        Console.WriteLine("Engine started!");
    }
}
```

**Создание объектов:**

Объект класса создается с использованием ключевого слова `new`. Это выделяет память для объекта и вызывает его конструктор.

```csharp
csharpCopy codeCar myCar = new Car();
myCar.Model = "Toyota";
myCar.Year = 2022;
myCar.StartEngine();  // Вызов метода объекта
```

#### **Поля и методы классов**

**Поля класса:**

Поля представляют собой переменные, связанные с классом. Они определяют состояние объекта.

```csharp
csharpCopy codepublic class Dog
{
    public string Name;
    public int Age;
}
```

**Методы класса:**

Методы - это функции, связанные с классом. Они определяют поведение объекта.

```csharp
csharpCopy codepublic class Circle
{
    public double Radius;

    // Метод для вычисления площади круга
    public double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
}
```

#### **Конструкторы и деструкторы**

**Конструкторы:**

Конструктор - это метод, вызываемый при создании объекта. Он инициализирует поля объекта.

```csharp
csharpCopy codepublic class Person
{
    public string Name;
    public int Age;

    // Конструктор с параметрами
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}
```

**Деструкторы:**

Деструктор - это метод, вызываемый перед удалением объекта из памяти. В C# деструкторы редко используются, так как сборка мусора автоматически управляет освобождением ресурсов.

```csharp
csharpCopy codepublic class MyClass
{
    // Деструктор
    ~MyClass()
    {
        // Код деструктора
    }
}
```

#### **Свойства и индексаторы**

**Свойства:**

Свойства предоставляют контролируемый доступ к полям класса, обеспечивая геттеры и сеттеры.

```csharp
csharpCopy codepublic class Rectangle
{
    private double _length;

    // Свойство с геттером и сеттером
    public double Length
    {
        get { return _length; }
        set { _length = value > 0 ? value : 0; }
    }
}
```

**Индексаторы:**

Индексаторы позволяют обращаться к объекту, как к массиву.

```csharp
csharpCopy codepublic class MyArray
{
    private int[] array = new int[10];

    // Индексатор
    public int this[int index]
    {
        get { return array[index]; }
        set { array[index] = value; }
    }
}
```

Все эти концепции в совокупности позволяют создавать гибкие и мощные классы в языке C#, способствуя легкости использования и читаемости кода.

## Наследование и полиморфизм

#### **Иерархия классов и наследование**

**Иерархия классов:**

Иерархия классов представляет собой организацию классов в виде дерева, где более общие классы расположены выше, а более специализированные - ниже. Наследование позволяет классам наследовать свойства и методы от родительских классов.

```csharp
csharpCopy code// Родительский класс
public class Shape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a shape");
    }
}

// Дочерний класс, наследующий от Shape
public class Circle : Shape
{
    public void DrawCircle()
    {
        Console.WriteLine("Drawing a circle");
    }
}
```

**Использование наследования:**

```csharp
csharpCopy codeCircle myCircle = new Circle();
myCircle.Draw();        // Метод из родительского класса Shape
myCircle.DrawCircle();  // Метод из дочернего класса Circle
```

#### **Перегрузка методов и операторов**

**Перегрузка методов:**

Перегрузка методов позволяет создавать несколько методов с одним и тем же именем, но разными параметрами.

```csharp
csharpCopy codepublic class MathOperations
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public double Add(double a, double b)
    {
        return a + b;
    }
}
```

**Перегрузка операторов:**

Перегрузка операторов позволяет определить поведение операторов для пользовательских типов.

```csharp
csharpCopy codepublic class ComplexNumber
{
    public double Real { get; set; }
    public double Imaginary { get; set; }

    public static ComplexNumber operator +(ComplexNumber a, ComplexNumber b)
    {
        return new ComplexNumber { Real = a.Real + b.Real, Imaginary = a.Imaginary + b.Imaginary };
    }
}
```

#### **Абстрактные классы и интерфейсы**

**Абстрактные классы:**

Абстрактные классы не могут быть созданы напрямую и могут содержать абстрактные методы. Абстрактный метод не имеет тела и должен быть реализован в дочерних классах.

```csharp
csharpCopy codepublic abstract class Animal
{
    public abstract void MakeSound();
}
```

**Интерфейсы:**

Интерфейс определяет совокупность методов, которые класс должен реализовать. Класс может реализовывать несколько интерфейсов.

```csharp
csharpCopy codepublic interface IDrawable
{
    void Draw();
}

public class Circle : IDrawable
{
    public void Draw()
    {
        Console.WriteLine("Drawing a circle");
    }
}
```

#### **Полиморфизм на основе интерфейсов**

**Полиморфизм на основе интерфейсов:**

Интерфейс позволяет обращаться к объектам разных классов через общий интерфейс, что обеспечивает гибкость и расширяемость.

```csharp
csharpCopy codepublic interface IShape
{
    void Draw();
}

public class Circle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a circle");
    }
}

public class Rectangle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a rectangle");
    }
}
```

```csharp
csharpCopy codeList<IShape> shapes = new List<IShape>();
shapes.Add(new Circle());
shapes.Add(new Rectangle());

foreach (var shape in shapes)
{
    shape.Draw();  // Вызов метода через интерфейс
}
```

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

## Инкапсуляция и модификаторы доступа

#### **Принципы инкапсуляции**

**Инкапсуляция:**

Инкапсуляция - это принцип объектно-ориентированного программирования, который заключается в скрытии деталей реализации объекта от внешнего мира и предоставлении интерфейса для взаимодействия с объектом. Она позволяет управлять доступом к данным и методам объекта.

Пример:

```csharp
csharpCopy codepublic class BankAccount
{
    private double balance;

    // Метод для изменения баланса
    public void Deposit(double amount)
    {
        if (amount > 0)
            balance += amount;
    }

    // Метод для получения баланса
    public double GetBalance()
    {
        return balance;
    }
}
```

#### **Модификаторы доступа: public, private, protected, internal, protected internal**

**Модификаторы доступа:**

* `public`: Класс, метод, свойство или поле с модификатором `public` доступны из любого места в программе.
* `private`: Элемент с модификатором `private` доступен только в пределах своего класса. Другие классы не могут напрямую обращаться к `private` элементам.
* `protected`: Элемент с модификатором `protected` доступен внутри своего класса и его подклассов.
* `internal`: Элемент с модификатором `internal` доступен в пределах текущей сборки. Другие сборки не могут напрямую обращаться к `internal` элементам.
* `protected internal`: Элемент с модификатором `protected internal` доступен внутри своего класса, его подклассов и в пределах текущей сборки.

Пример:

```csharp
csharpCopy codepublic class MyClass
{
    public int PublicField;
    private int PrivateField;
    protected int ProtectedField;
    internal int InternalField;
    protected internal int ProtectedInternalField;
}
```

#### **Свойства с модификаторами доступа**

**Свойства:**

Свойства предоставляют контролируемый доступ к полям класса. Они позволяют использовать методы для чтения и записи значений, что обеспечивает более гибкий контроль.

```csharp
csharpCopy codepublic class Person
{
    private string name;

    // Свойство с модификаторами доступа
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}
```

Свойства могут использовать модификаторы доступа так же, как и поля, что позволяет более точно управлять доступом к данным объекта.

## Принципы SOLID в ООП

#### **Принцип единственной ответственности (Single Responsibility Principle)**

**Принцип единственной ответственности (SRP):**

Этот принцип утверждает, что класс должен иметь только одну причину для изменения, то есть он должен быть ответственным только за одну важную часть функциональности.

Пример:

```csharp
csharpCopy code// Нарушение SRP
public class Employee
{
    public string Name { get; set; }
    public decimal CalculateSalary() { /* ... */ }
    public void SaveToDatabase() { /* ... */ }
}

// Соблюдение SRP
public class Employee
{
    public string Name { get; set; }
    public decimal CalculateSalary() { /* ... */ }
}

public class EmployeeRepository
{
    public void SaveToDatabase(Employee employee) { /* ... */ }
}
```

#### **Принцип открытости/закрытости (Open/Closed Principle)**

**Принцип открытости/закрытости (OCP):**

Этот принцип гласит, что класс должен быть открыт для расширения, но закрыт для модификации. Новая функциональность добавляется путем расширения класса, а не изменения его существующего кода.

Пример:

```csharp
csharpCopy code// Нарушение OCP
public class Rectangle
{
    public double Width { get; set; }
    public double Height { get; set; }
}

public class AreaCalculator
{
    public double CalculateArea(Rectangle rectangle)
    {
        return rectangle.Width * rectangle.Height;
    }
}

// Соблюдение OCP
public abstract class Shape
{
    public abstract double CalculateArea();
}

public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }

    public override double CalculateArea()
    {
        return Width * Height;
    }
}
```

#### **Принцип подстановки Барбары Лисков (Liskov Substitution Principle)**

**Принцип подстановки Барбары Лисков (LSP):**

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

Пример:

```csharp
csharpCopy code// Нарушение LSP
public class Bird
{
    public virtual void Fly() { /* ... */ }
}

public class Penguin : Bird
{
    public override void Fly()
    {
        throw new InvalidOperationException("Penguins can't fly");
    }
}

// Соблюдение LSP
public interface IFlyable
{
    void Fly();
}

public class Bird : IFlyable
{
    public void Fly() { /* ... */ }
}

public class Penguin : IFlyable
{
    public void Fly()
    {
        throw new InvalidOperationException("Penguins can't fly");
    }
}
```

#### **Принцип разделения интерфейса (Interface Segregation Principle)**

**Принцип разделения интерфейса (ISP):**

Этот принцип утверждает, что клиенты не должны зависеть от интерфейсов, которые они не используют. Если интерфейс становится слишком «толстым», его следует разделить на более мелкие, специфичные интерфейсы.

Пример:

```csharp
csharpCopy code// Нарушение ISP
public interface IWorker
{
    void Work();
    void TakeBreak();
}

public class Manager : IWorker
{
    public void Work() { /* ... */ }
    public void TakeBreak() { /* ... */ }
}

public class Robot : IWorker
{
    public void Work() { /* ... */ }
    public void TakeBreak() { /* ... */ }
}

// Соблюдение ISP
public interface IWorker
{
    void Work();
}

public interface IBreakable
{
    void TakeBreak();
}

public class Manager : IWorker, IBreakable
{
    public void Work() { /* ... */ }
    public void TakeBreak() { /* ... */ }
}

public class Robot : IWorker
{
    public void Work() { /* ... */ }
}
```

#### **Принцип инверсии зависимостей (Dependency Inversion Principle)**

**Принцип инверсии зависимостей (DIP):**

Этот принцип утверждает, что модули верхнего уровня не должны зависеть от модулей нижнего уровня, а оба типа модулей должны зависеть от абстракций. Абстракции не должны зависеть от деталей, детали должны зависеть от абстракций.

Пример:

```csharp
csharpCopy code// Нарушение DIP
public class LightBulb
{
    public void TurnOn() { /* ... */ }
    public void TurnOff() { /* ... */ }
}

public class Switch
{
    private LightBulb bulb;

    public Switch(LightBulb bulb)
    {
        this.bulb = bulb;
    }

    public void Toggle()
    {
        if (/* some condition */)
            bulb.TurnOn();
        else
            bulb.TurnOff();
    }
}

// Соблюдение DIP
public interface ISwitchable
{
    void TurnOn();
    void TurnOff();
}

public class LightBulb : ISwitchable
{
    public void TurnOn() { /* ... */ }
    public void TurnOff() { /* ... */ }
}

public class Switch
{
    private ISwitchable device;

    public Switch(ISwitchable device)
    {
        this.device = device;
    }

    public void Toggle()
    {
        if (/* some condition */)
            device.TurnOn();
        else
            device.TurnOff();
    }
}
```

Соблюдение принципов SOLID обеспечивает гибкость, расширяемость и легкость поддержки кода, делая его более устойчивым к изменениям и повышая его качество.

## Практические примеры ООП в C\#

#### **Создание и использование классов**

**Создание классов:**

```csharp
csharpCopy codepublic class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public void DisplayInfo()
    {
        Console.WriteLine($"Name: {Name}, Age: {Age}");
    }
}

// Использование класса
Person person = new Person();
person.Name = "John";
person.Age = 30;
person.DisplayInfo();
```

#### **Работа с наследованием и полиморфизмом**

**Наследование и полиморфизм:**

```csharp
csharpCopy codepublic class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Animal makes a sound");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Dog barks");
    }
}

public class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Cat meows");
    }

    public void Purr()
    {
        Console.WriteLine("Cat purrs");
    }
}

// Использование полиморфизма
Animal dog = new Dog();
Animal cat = new Cat();

dog.MakeSound(); // "Dog barks"
cat.MakeSound(); // "Cat meows"

// Приведение типов
Cat myCat = (Cat)cat;
myCat.Purr(); // "Cat purrs"
```

#### **Применение принципов SOLID в проекте**

**Применение принципов SOLID:**

* **Принцип единственной ответственности (SRP):** Разделение классов для обеспечения одной ответственности.
* **Принцип открытости/закрытости (OCP):** Использование интерфейсов и абстрактных классов для расширения функциональности.
* **Принцип подстановки Барбары Лисков (LSP):** Правильное использование наследования, чтобы объекты производных классов могли заменить объекты базового класса.
* **Принцип разделения интерфейса (ISP):** Разделение интерфейсов для предотвращения зависимости от ненужных методов.
* **Принцип инверсии зависимостей (DIP):** Использование интерфейсов и внедрение зависимостей для создания гибких систем.

## **Лучшие практики при разработке с использованием ООП**

#### **Эффективное использование классов и объектов**

* **Использование композиции:** Предпочтение композиции объектов перед наследованием для достижения гибкости.
* **Изоляция изменений:** Обеспечение, чтобы изменения в одном классе не влияли на другие части системы.

#### **Проектирование гибких и расширяемых классов**

* **Использование интерфейсов:** Использование интерфейсов для определения контрактов и реализации множественного наследования.
* **Правильное использование наследования:** Разработка иерархии классов так, чтобы она была легко расширяемой и поддерживаемой.

#### **Обеспечение читаемости и понятности кода**

* **Ясные имена:** Именование классов и методов так, чтобы их назначение было понятным.
* **Комментарии и документация:** Предоставление хорошей документации и комментариев для улучшения понимания кода.

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

#### **Роль ООП в современной разработке**

**ООП в современной разработке:** Объектно-ориентированное программирование является фундаментальным подходом к разработке программного обеспечения, обеспечивая гибкость, повторное использование и легкость поддержки кода.

#### **Перспективы развития ООП и новые подходы**

**Перспективы ООП:** Развитие новых языков программирования и фреймворков, поддерживающих современные принципы и требования разработки.

#### **Значение принципов SOLID для создания высококачественного кода**

**Принципы SOLID:** Солидные принципы обеспечивают создание кода, который легко поддерживать, расширять и изменять, а также содействуют созданию устойчивых и эффективных приложений. Их соблюдение является ключевым фактором для написания высококачественного кода.

***

{% embed url="<https://www.youtube.com/watch?v=j-GeCN2JHaE>" %}

{% embed url="<https://www.youtube.com/watch?v=XV5SbgqPOao>" %}

***

## Упражнения

#### **Создание класса**

Создайте класс "Студент" с полями для имени, возраста и средней оценки. Напишите конструктор для инициализации этих полей и метод для вывода информации о студенте.

<details>

<summary>Решение</summary>

```csharp
using System;

public class Student
{
    // Поля класса
    private string name;
    private int age;
    private double averageGrade;

    // Конструктор класса
    public Student(string name, int age, double averageGrade)
    {
        this.name = name;
        this.age = age;
        this.averageGrade = averageGrade;
    }

    // Метод для вывода информации о студенте
    public void DisplayInfo()
    {
        Console.WriteLine($"Имя: {name}");
        Console.WriteLine($"Возраст: {age}");
        Console.WriteLine($"Средний балл: {averageGrade}");
    }
}

class Program
{
    static void Main()
    {
        // Создание объекта класса Student
        Student student1 = new Student("Иванов Иван", 20, 4.5);

        // Вывод информации о студенте
        student1.DisplayInfo();
    }
}
```

</details>

#### **Наследование**

Реализуйте иерархию классов "Фигура" и "Прямоугольник". Фигура должна иметь метод для вычисления площади, а прямоугольник - метод для вычисления периметра.

<details>

<summary>Решение</summary>

```csharp
using System;

// Базовый класс "Фигура"
public class Figure
{
    // Виртуальный метод для вычисления площади
    public virtual double CalculateArea()
    {
        return 0;
    }
}

// Производный класс "Прямоугольник"
public class Rectangle : Figure
{
    // Свойства для длин сторон прямоугольника
    public double Length { get; set; }
    public double Width { get; set; }

    // Реализация метода для вычисления площади прямоугольника
    public override double CalculateArea()
    {
        return Length * Width;
    }

    // Метод для вычисления периметра прямоугольника
    public double CalculatePerimeter()
    {
        return 2 * (Length + Width);
    }
}

class Program
{
    static void Main()
    {
        // Создание объекта класса Rectangle
        Rectangle rectangle = new Rectangle { Length = 5, Width = 3 };

        // Вычисление и вывод площади и периметра
        Console.WriteLine($"Площадь прямоугольника: {rectangle.CalculateArea()}");
        Console.WriteLine($"Периметр прямоугольника: {rectangle.CalculatePerimeter()}");
    }
}
```

</details>

#### **Инкапсуляция**

Создайте класс "Банковский счет" с приватным полем баланса. Реализуйте методы для пополнения и снятия денег с счета, а также метод для получения текущего баланса.

<details>

<summary>Решение</summary>

```csharp
using System;

public class BankAccount
{
    private double balance; // Приватное поле для хранения баланса

    // Конструктор для инициализации начального баланса
    public BankAccount(double initialBalance)
    {
        if (initialBalance < 0)
        {
            throw new ArgumentException("Начальный баланс не может быть отрицательным.");
        }

        balance = initialBalance;
    }

    // Метод для пополнения счета
    public void Deposit(double amount)
    {
        if (amount < 0)
        {
            throw new ArgumentException("Сумма пополнения не может быть отрицательной.");
        }

        balance += amount;
    }

    // Метод для снятия денег со счета
    public void Withdraw(double amount)
    {
        if (amount < 0)
        {
            throw new ArgumentException("Сумма снятия не может быть отрицательной.");
        }

        if (amount > balance)
        {
            throw new InvalidOperationException("Недостаточно средств на счете.");
        }

        balance -= amount;
    }

    // Метод для получения текущего баланса
    public double GetBalance()
    {
        return balance;
    }
}

class Program
{
    static void Main()
    {
        // Создание объекта класса BankAccount с начальным балансом 1000
        BankAccount account = new BankAccount(1000);

        // Пополнение счета на 500
        account.Deposit(500);

        // Снятие 200 счета
        account.Withdraw(200);

        // Вывод текущего баланса
        Console.WriteLine($"Текущий баланс: {account.GetBalance()}");
    }
}
```

</details>

#### **Полиморфизм**

Создайте интерфейс "Фигура" с методом для вычисления площади. Реализуйте этот интерфейс в классах "Круг" и "Квадрат". Создайте массив фигур и вычислите суммарную площадь.

<details>

<summary>Решение</summary>

```csharp
using System;

// Интерфейс "Фигура" с методом для вычисления площади
public interface IFigure
{
    double CalculateArea();
}

// Класс "Круг", реализующий интерфейс "Фигура"
public class Circle : IFigure
{
    private double radius;

    public Circle(double radius)
    {
        this.radius = radius;
    }

    public double CalculateArea()
    {
        return Math.PI * radius * radius;
    }
}

// Класс "Квадрат", реализующий интерфейс "Фигура"
public class Square : IFigure
{
    private double side;

    public Square(double side)
    {
        this.side = side;
    }

    public double CalculateArea()
    {
        return side * side;
    }
}

class Program
{
    static void Main()
    {
        // Создание массива фигур
        IFigure[] figures = new IFigure[]
        {
            new Circle(3),
            new Square(4),
            new Circle(2.5),
            new Square(5)
        };

        // Вычисление суммарной площади всех фигур
        double totalArea = CalculateTotalArea(figures);

        Console.WriteLine($"Суммарная площадь фигур: {totalArea}");
    }

    // Метод для вычисления суммарной площади массива фигур
    static double CalculateTotalArea(IFigure[] figures)
    {
        double totalArea = 0;

        foreach (var figure in figures)
        {
            totalArea += figure.CalculateArea();
        }

        return totalArea;
    }
}
```

</details>

#### **Абстрактные классы**

Создайте абстрактный класс "Транспортное средство" с абстрактным методом "Передвижение". Реализуйте этот класс в двух наследниках: "Автомобиль" и "Велосипед".

<details>

<summary>Решение</summary>

```csharp
using System;

// Абстрактный класс "Транспортное средство"
public abstract class Transport
{
    // Абстрактный метод "Передвижение"
    public abstract void Move();
}

// Наследник "Автомобиль"
public class Car : Transport
{
    public override void Move()
    {
        Console.WriteLine("Автомобиль двигается по дороге.");
    }
}

// Наследник "Велосипед"
public class Bicycle : Transport
{
    public override void Move()
    {
        Console.WriteLine("Велосипед двигается по велосипедной дорожке.");
    }
}

class Program
{
    static void Main()
    {
        // Создание экземпляров классов
        Transport car = new Car();
        Transport bicycle = new Bicycle();

        // Вызов метода "Передвижение" для каждого транспортного средства
        car.Move();
        bicycle.Move();
    }
}
```

</details>

#### **Композиция**

Создайте класс "Дом" с полем для списка комнат. Каждая комната может быть отдельным объектом класса "Комната". Реализуйте метод для подсчета общей площади дома.

<details>

<summary>Решение</summary>

```csharp
using System;
using System.Collections.Generic;

// Класс "Комната"
public class Room
{
    public double Area { get; set; }

    public Room(double area)
    {
        Area = area;
    }
}

// Класс "Дом"
public class House
{
    private List<Room> rooms;

    public House()
    {
        rooms = new List<Room>();
    }

    // Метод для добавления комнаты в список комнат дома
    public void AddRoom(Room room)
    {
        rooms.Add(room);
    }

    // Метод для подсчета общей площади дома
    public double CalculateTotalArea()
    {
        double totalArea = 0;

        foreach (var room in rooms)
        {
            totalArea += room.Area;
        }

        return totalArea;
    }
}

class Program
{
    static void Main()
    {
        // Создание объектов комнат и дома
        Room livingRoom = new Room(25.5);
        Room bedroom = new Room(20.0);
        Room kitchen = new Room(15.75);

        House myHouse = new House();

        // Добавление комнат в список комнат дома
        myHouse.AddRoom(livingRoom);
        myHouse.AddRoom(bedroom);
        myHouse.AddRoom(kitchen);

        // Подсчет общей площади дома и вывод результата
        double totalArea = myHouse.CalculateTotalArea();
        Console.WriteLine($"Общая площадь дома: {totalArea} кв. м");
    }
}
```

</details>

***

## Вопросы

#### **Что такое объект в контексте объектно-ориентированного программирования?**

#### **Какие основные принципы ООП?**

#### **Разница между классом и объектом в C#?**

#### **Что такое наследование и как оно применяется в ООП?**

#### **Как работает инкапсуляция в языке программирования C#?**

#### **Что представляет собой полиморфизм и как его реализовать в C#?**

#### **В чем разница между абстрактным классом и интерфейсом?**

#### **Что такое композиция в объектно-ориентированном программировании?**

#### **Какие основные преимущества использования ООП в разработке программного обеспечения?**

#### **Как обеспечить безопасность данных при работе с объектами в C#?**

***

## Тесты

{% embed url="<https://docs.google.com/forms/d/e/1FAIpQLSe_gXGkb8PE7CnvQzgxiDs2pFhy19YMXNAWw5kkigJukZHEIg/viewform?usp=sf_link>" fullWidth="true" %}
