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

В данной главе рассматриваются основы объектно-ориентированного программирования (ООП) с использованием языка C#.

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

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

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

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

  • Классы и объекты: Класс представляет собой шаблон для создания объектов. Объект - это экземпляр класса, обладающий определенными свойствами и методами.

  • Наследование: Механизм, позволяющий создавать новый класс на основе существующего, наследуя его свойства и методы. Это обеспечивает повторное использование кода и иерархию классов.

  • Инкапсуляция: Принцип, заключающийся в объединении данных и методов, работающих с этими данными, в единый объект. Инкапсуляция скрывает детали реализации и обеспечивает контролируемый доступ.

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

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

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

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

  • Повторное использование кода: Классы и объекты могут быть повторно использованы в различных частях программы или даже в разных проектах, что экономит время и ресурсы.

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

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

  • Разделение ответственности: ООП способствует разделению кода на небольшие, самодостаточные блоки (классы), что упрощает поддержку и разработку.

  • Инкапсуляция и контролируемый доступ: Инкапсуляция обеспечивает скрытие деталей реализации, что способствует контролируемому и безопасному доступу к данным.

  • Повышение повторного использования кода: Механизмы наследования и композиции в ООП позволяют повторно использовать код, уменьшая дублирование.

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

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

  • Классы: Абстракция, представляющая собой шаблон для создания объектов. Класс определяет свойства (поля) и методы, которые будут присутствовать у объектов.

  • Объекты: Экземпляры классов, обладающие конкретными значениями свойств и возможностью вызова методов.

  • Наследование: Механизм, позволяющий новым классам использовать свойства и методы существующих классов, способствуя повторному использованию кода.

  • Инкапсуляция: Упаковка данных и методов, работающих с ними, в единый объект (класс), предоставляя контролируемый доступ и скрывая детали реализации.

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

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

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

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

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

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

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

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

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

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

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

Поля класса:

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

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

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

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

csharpCopy codepublic class Circle
{
    public double Radius;

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

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

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

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

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

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

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

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

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

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

Свойства:

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

csharpCopy codepublic class Rectangle
{
    private double _length;

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

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

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

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

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

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

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

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

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

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

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");
    }
}

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

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

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

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

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

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

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

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

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

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 };
    }
}

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

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

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

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

Интерфейсы:

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

csharpCopy codepublic interface IDrawable
{
    void Draw();
}

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

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

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

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

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");
    }
}
csharpCopy codeList<IShape> shapes = new List<IShape>();
shapes.Add(new Circle());
shapes.Add(new Rectangle());

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

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

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

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

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

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

Пример:

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 доступен внутри своего класса, его подклассов и в пределах текущей сборки.

Пример:

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

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

Свойства:

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

csharpCopy codepublic class Person
{
    private string name;

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

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

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

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

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

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

Пример:

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):

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

Пример:

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):

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

Пример:

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):

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

Пример:

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):

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

Пример:

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#

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

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

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();

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

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

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



Упражнения

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

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

Решение
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();
    }
}

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

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

Решение
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()}");
    }
}

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

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

Решение
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()}");
    }
}

Полиморфизм

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

Решение
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;
    }
}

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

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

Решение
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();
    }
}

Композиция

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

Решение
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} кв. м");
    }
}

Вопросы

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

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

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

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

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

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

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

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

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

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


Тесты

Last updated