Инкапсуляция в C#: модификаторы доступа и защита данных
Что такое инкапсуляция
Инкапсуляция — это процесс объединения данных и методов в единый блок (класс) и ограничение прямого доступа к внутренней реализации. В объектно-ориентированном программировании инкапсуляция скрывает детали реализации.
Абстракция и инкапсуляция связаны: абстракция показывает что делает объект, инкапсуляция определяет как это реализовано и ограничивает доступ к внутренностям.
Модификаторы доступа в C#
Инкапсуляция реализуется через модификаторы доступа (access specifiers). C# поддерживает:
| Модификатор | Видимость |
|---|---|
public | Доступ из любого кода |
private | Только внутри своего класса (по умолчанию для членов класса) |
protected | Внутри своего класса и в производных классах |
internal | Внутри текущей сборки (assembly) |
protected internal | Внутри сборки ИЛИ в производных классах (объединение) |
private protected | Внутри класса И в производных классах ВНУТРИ ТОЙ ЖЕ СБОРКИ (C# 7.2+) |
Public — публичный доступ
Члены доступны извне класса через экземпляр.
public class Rectangle
{
public double Length;
public double Width;
public double GetArea() => Length * Width;
public void Display()
{
Console.WriteLine($"Length: {Length}");
Console.WriteLine($"Width: {Width}");
Console.WriteLine($"Area: {GetArea()}");
}
}
class Program
{
static void Main()
{
Rectangle r = new Rectangle();
r.Length = 4.5;
r.Width = 3.5;
r.Display(); // доступ к public полям и методам
}
}
Private — приватный доступ
Члены скрыты от внешнего кода. Доступ только методам того же класса. Это основа инкапсуляции — поля делают private, а доступ предоставляют через public свойства/методы.
public class Rectangle
{
private double length;
private double width;
public void AcceptDetails()
{
Console.Write("Length: ");
length = Convert.ToDouble(Console.ReadLine());
Console.Write("Width: ");
width = Convert.ToDouble(Console.ReadLine());
}
public double GetArea() => length * width;
public void Display()
{
Console.WriteLine($"Length: {length}");
Console.WriteLine($"Width: {width}");
Console.WriteLine($"Area: {GetArea()}");
}
}
Protected — защищённый доступ
Доступен в производных классах. Используется для реализации наследования.
public class Shape
{
protected double width;
protected double height;
}
public class Rectangle : Shape
{
public double GetArea() => width * height; // доступ к protected полям базового класса
}
Internal — внутренний доступ
Доступен в любой класс/метод внутри той же сборки (assembly / проект). По умолчанию для классов без модификатора.
internal class InternalClass { } // видно только в этой сборке
public class PublicClass
{
internal int InternalField; // видно в этой сборке
}
В примере из оригинала метод GetArea() без модификатора неявно private (для членов класса).
Protected Internal — защищённый внутренний
Доступен: (1) везде в текущей сборке ИЛИ (2) в производных классах (даже в других сборках).
Private Protected (C# 7.2+)
Доступен: в производных классах, но ТОЛЬКО внутри той же сборки. Более строго, чем protected internal.
Свойства — идиоматический способ инкапсуляции
Вместо пар методов GetX/SetX в C# используются свойства:
public class Rectangle
{
private double length;
private double width;
public double Length
{
get => length;
set => length = value > 0 ? value : throw new ArgumentException("Длина > 0");
}
public double Width { get; set; } // авто-свойство (с скрытым backing field)
public double Area => Length * Width; // read-only вычисляемое свойство
}
Резюме: когда что использовать
private— по умолчанию для полей и внутренней логикиpublic— для публичного API классаprotected— для членов, нужных наследникамinternal— для внутренней логики сборкиprotected internal— редко, для расширяемости между сборкамиprivate protected— для реализации базового класса, скрытой от внешних сборок
Язык C
- Классы и объекты в C#: Фундаменты надёжного ООП
- Модификаторы доступа в C#: public, private, protected, internal и другие
- Ключевое слово static в C#: статические переменные, методы и классы
- Абстрактные классы и методы в C#: практическое руководство
- Вложенные классы в C#: определение, использование и наследование
- Частичные классы и методы в C#: понимание и применение
- Sealed-классы и sealed-методы в C#: когда использовать, примеры и повышение безопасности кода
- Инкапсуляция в Java: сокрытие данных и контроль доступа
- Полиморфизм в C++: практическое руководство
- Абстракция данных в C++: разделение интерфейса и реализации