Menu
CoddyTech

Свойства для инкапсуляции

Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy. Урок 32 из 70.

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

Этот шаблон сочетает закрытое поле с открытым свойством, методы доступа которого содержат проверку или логику:

public class Temperature
{
    private double celsius;
    
    public double Celsius
    {
        get { return celsius; }
        set
        {
            if (value < -273.15)
                celsius = -273.15;  // Минимум — абсолютный ноль
            else
                celsius = value;
        }
    }
}

Теперь внешний код не может задать невозможную температуру. Свойство выступает в роли привратника, гарантируя, что ваш объект всегда остаётся в допустимом состоянии. Так работает инкапсуляция: внутренние данные защищены, но по-прежнему доступны через контролируемый интерфейс.

Ты также можешь использовать свойства для вычисления значений или запуска побочных эффектов:

public double Fahrenheit
{
    get { return celsius * 9 / 5 + 32; }
    set { celsius = (value - 32) * 5 / 9; }
}

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

challenge icon

Задание

Легко

Давайте создадим систему учёта товаров, которая использует свойства для защиты целостности данных. Вы создадите класс, в котором цены не могут быть отрицательными, а количество всегда находится в допустимых пределах, — так вы увидите, как свойства выступают в роли защитников ваших данных.

Вы организуете код в двух файлах:

  • Product.cs: Создайте класс Product в пространстве имён Inventory, который управляет информацией о товаре и проверяет её с помощью свойств. В вашем классе товара должны быть:
    • Приватное поле price (decimal) и общедоступное свойство Price, которое гарантирует, что цена не опустится ниже 0: если кто-то попытается задать отрицательную цену, вместо неё должно быть сохранено значение 0
    • Приватное поле quantity (int) и общедоступное свойство Quantity, которое удерживает значения в пределах от 0 до 1000: значения меньше 0 становятся равны 0, значения больше 1000 становятся равны 1000
    • Общедоступное автоматически реализуемое свойство Name (string)
    • Вычисляемое свойство только для чтения TotalValue, которое возвращает Price * Quantity
    Добавьте конструктор, который принимает название, цену и количество (именно в таком порядке) и задаёт все значения через свойства, чтобы применялась проверка.
  • Program.cs: В главном файле создайте объект Product, используя введённые значения. Затем попробуйте изменить цену и количество, используя дополнительные входные значения, которые могут быть недопустимыми. Выведите состояние товара после создания и после каждого изменения, чтобы увидеть, как свойства защищают данные.

Вы получите пять входных значений:

  • Название товара
  • Начальная цена (decimal)
  • Начальное количество (целое число)
  • Новая цена (decimal, может быть отрицательной)
  • Новое количество (целое число, может выходить за допустимый диапазон)

Выведите результат в следующем формате:

After creation:
{Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
After modifications:
{Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}

Например, если входные данные — Laptop, 999.99, 50, -100 и 1500, результат должен быть таким:

After creation:
Laptop: Price=999.99, Qty=50, Total=49999.50
After modifications:
Laptop: Price=0, Qty=1000, Total=0

Обратите внимание, как отрицательная цена стала равна 0, а количество 1500 было ограничено значением 1000. Ваши свойства защищают объект от недопустимых состояний — в действии инкапсуляция!

Попробуйте сами

using System;
using Inventory;

class Program
{
    public static void Main(string[] args)
    {
        // Считать входные данные
        string name = Console.ReadLine();
        decimal initialPrice = Convert.ToDecimal(Console.ReadLine());
        int initialQuantity = Convert.ToInt32(Console.ReadLine());
        decimal newPrice = Convert.ToDecimal(Console.ReadLine());
        int newQuantity = Convert.ToInt32(Console.ReadLine());

        // TODO: Создать Product с начальными значениями
        
        // TODO: Вывести состояние продукта после создания
        Console.WriteLine("After creation:");
        // Формат вывода: {Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
        
        // TODO: Изменить цену и количество, используя новые значения
        
        // TODO: Вывести состояние продукта после изменений
        Console.WriteLine("After modifications:");
        // Формат вывода: {Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C#