Свойства для инкапсуляции
Часть раздела Объектно-ориентированное программирование путешествия по 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; }
}Внешний мир видит два свойства, но внутри есть только одно поле. Свойства позволяют менять детали реализации, не нарушая работу кода, использующего ваш класс, — это ключевое преимущество правильной инкапсуляции.
Задание
ЛегкоДавайте создадим систему учёта товаров, которая использует свойства для защиты целостности данных. Вы создадите класс, в котором цены не могут быть отрицательными, а количество всегда находится в допустимых пределах, — так вы увидите, как свойства выступают в роли защитников ваших данных.
Вы организуете код в двух файлах:
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}
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыПространства имен и директивыВведение в классы и объектыКлючевое слово 'this'Методы и параметрыПоля и свойстваКонструкторыИнициализаторы объектовИтоги — Простой калькулятор4Наследование
Основы синтаксиса наследования (:)Ключевое слово 'base'Ключевые слова Virtual и OverrideЗапечатанные классыБазовый класс 'object'Итоги — Иерархия сотрудников7Продвинутые возможности
Перегрузка операторовИндексаторы (this[])Переопределение ToString()Методы расширенияПовторение — Пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПотокобезопасный SingletonПаттерн FactoryПаттерн Observer (События)Паттерн Strategy13Финальные испытания
Платформа для онлайн-обученияКомпонент игрового персонажаСервис аренды транспорта2Свойства и статические члены
Автоматически реализуемые свойстваСвойства только для чтения и записиСтатические поля и методыСтатические классыЧлены в виде выражений5Полиморфизм и интерфейсы
Полиморфизм: компиляция vs выполнениеИнтерфейс vs абстрактный классМножественные интерфейсыЯвные интерфейсыUpcasting и DowncastingИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция вместо наследованияGenerics (классы и методы)Делегаты и событияАтрибуты и рефлексияIDisposable и оператор usingОсновы Dependency Injection11Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн Компоновщик3Архитектура классов
Экземплярные и статические данныеКлючевые слова 'readonly' и 'const'Опорные поляПовторение — Менеджер банковских счетов6Инкапсуляция
Модификаторы доступаСвойства для инкапсуляцииРеализация скрытия данныхПаттерны неизменяемостиИтоги — Записи студентов9Переменное количество аргументов
Ключевое слово 'params'Необязательные параметрыИменованные аргументыПерегрузка методовПотренируйтесь самостоятельно: Онлайн-компилятор C#