Классы и инкапсуляция в C#
Класс — базовая единица моделирования в C#. Он объединяет состояние (поля) и поведение (методы) в один тип и решает, что снаружи видно, а что скрыто. Объект — конкретный экземпляр класса в куче: класс описывает форму, объект хранит значения. Почти вся дальнейшая объектная модель C# — наследование, полиморфизм, интерфейсы — строится поверх этих понятий.
Инкапсуляция — не про «сделать поля private ради галочки», а про сохранение инвариантов: конструктор приводит новый объект в корректное состояние, модификаторы доступа решают, кто может это состояние менять, а абстракция прячет детали за узким контрактом. Специфика C#, на которой спотыкаются: компилятор убирает конструктор по умолчанию, как только вы объявили свой; this(...) и base(...) связывают конструкторы в строгом порядке снизу-вверх; член без модификатора — private, а не public; абстрактный класс, в отличие от интерфейса, несёт реализацию и состояние. Разбор по слоям — ниже.
Карта темы
- Классы и объекты —
classописывает ссылочный тип, объект — его конкретный экземпляр в куче, а переменная хранит ссылку. - Конструкторы — что делает конструктор при
new, почему объявив свой вы теряете конструктор по умолчанию, перегрузка. - Цепочки конструкторов —
: this(...)внутри класса,: base(...)к базовому, построение снизу-вверх. - Модификаторы доступа — шесть уровней от
publicдоprivate protectedи почему умолчание члена —private. - Абстракция — прятать реализацию за публичным контрактом, свойства вместо полей, абстрактные члены.
- Абстрактные классы —
abstractкласс с состоянием и реализацией против чистого контракта интерфейса.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Считать, что b = a копирует объект | Для class копируется только ссылка — обе переменные меняют один объект в куче |
| Ждать конструктор по умолчанию после своего | Объявив любой конструктор, вы теряете неявный public без параметров — старый new T() перестаёт компилироваться |
Путать : this(...) и : base(...) | this идёт к конструктору того же класса, base — к базовому; перепутав, вы ломаете цепочку инициализации |
| Оставлять поле без модификатора «как публичное» | Член класса без модификатора по умолчанию private, а не public |
Путать protected internal и private protected | Первый — ИЛИ (шире), второй — И (уже); перепутанный союз открывает или закрывает лишний доступ |
| Считать абстрактный класс «интерфейсом с другим словом» | Абстрактный класс несёт поля, конструктор и реализацию и допускает лишь одиночное наследование |
Пытаться создать абстрактный класс через new | Ошибка компиляции — абстрактный тип инстанцируют только через производный |
Значение для собеседований
ООП-основы спрашивают почти на любом C#-интервью — но проверяют не заученные определения, а модель типов и их состояния. Кандидат, который объясняет class через «ссылочный тип-чертёж, а объект — экземпляр в куче, на который переменная держит ссылку», сразу выделяется на фоне «ну, это шаблон».
Что обычно проверяют:
- Разница класса (определение) и объекта (экземпляр в куче) и что переменная хранит ссылку.
- Что делает конструктор и когда пропадает неявный конструктор по умолчанию.
- Смысл
: this(...)против: base(...)и порядок построения «база первой». - Все шесть модификаторов доступа и умолчание
privateдля члена класса. - Абстракция как узкий публичный контракт поверх скрытой реализации.
- Когда брать абстрактный класс, а когда интерфейс.
Типичный неверный ответ: «Абстрактный класс — это то же, что интерфейс». Это открывает разговор о том, что абстрактный класс несёт состояние, конструктор и реализацию, допускает лишь одиночное наследование и моделирует «is-a», тогда как интерфейс — контракт возможности «can-do», который реализуют многие несвязанные типы.