Skip to content

Commit 5135a6c

Browse files
committed
feat: add encapsulation & inheritance pages
1 parent b4931cd commit 5135a6c

4 files changed

Lines changed: 179 additions & 25 deletions

File tree

docs/python/encapsulation.md

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,65 @@
1-
coming soon...
1+
## Определение
2+
!!! info ""
3+
**Инкапсуляция** (Encapsulation) — это принцип ООП, заключающийся в упаковке данных и методов для работы с ними внутри единого объекта с ограничением прямого доступа к его состоянию. Принцип **Чёрного ящика**.
4+
5+
## Для чего?
6+
<span class="badge">Инкапсуляция</span> создаёт границы вокруг объекта. Она скрывает внутреннее устройство и позволяет объекту самому контролировать допустимые изменения своего состояния.
7+
8+
Во внешнем коде важно **что** делает объект, а не **как именно** он это делает.
9+
10+
## Принцип чёрного ящика
11+
12+
Инкапсуляцию превращает объект в <span class="badge">Black Box</span> (чёрный ящик), защищая его внутренности:
13+
14+
- Скрытие реализации — извне доступен только публичный интерфейс объекта.
15+
- Контроль состояния — объект сам валидирует данные, прежде чем изменить свои атрибуты.
16+
- Независимость кода — внутреннюю логику можно переписать, не меняя код, который использует этот класс.
17+
18+
Извне взаимодейстие с объектом происходит через инструменты управления, не видя его внутреннего устройства.
19+
20+
## Инкапсуляция в Python
21+
22+
В отличие от языков с жёстким доступом, Python использует систему соглашений и декораторы:
23+
24+
- <span class="badge">_protected</span> — соглашение «только для внутреннего пользования», доступ сохраняется.
25+
- <span class="badge">__private</span> — механизм искажения имен (Name Mangling) для защиты от случайной перезаписи.
26+
- <span class="badge">@property</span> — способ превратить методы в атрибуты, добавляя логику доступа без изменения интерфейса.
27+
28+
| Формат | Название | Суть | Доступ снаружи
29+
| ------------- | ----------------------- | ------------------------ | -------------------------
30+
| `name` | Публичный | Обычный атрибут | Разрешён
31+
| `_protected` | Защищённый (Protected) | Соглашение "не трогать" | Можно, но не рекомендуется
32+
| `__private` | Приватный (Private) | Name Mangling | Только через <span class="badge">_Class__name</span>
33+
34+
Через свойства `@property` можно выдавать «красивый» атрибут, пряча внутри проверки и логику.
35+
36+
## Пример
37+
```python
38+
class Robot:
39+
def __init__(self, model: str):
40+
self.model = model # Публичный формат
41+
self._status = "active" # Защищённый формат
42+
self.__core_id = "RX-99" # Приватный формат
43+
44+
bot = Robot("Wall-E")
45+
46+
print(bot.model) # Работает без ограничений
47+
48+
print(bot._status) # Работает, но висит соглашение "не трогать"
49+
50+
print(bot.__core_id) # Классический принт выдаст ошибку AttributeError
51+
print(bot._Robot__core_id) # Доступ через искажённое имя, приватный формат
52+
53+
```
54+
55+
## Ключевые мысли
56+
- Инкапсуляция снижает зависимость между модулями, разделяя внешние методы управления и скрытую внутреннюю логику.
57+
- Объект выступает гарантом собственной стабильности, блокируя попытки внешнего кода установить некорректные или конфликтующие данные.
58+
- Такой подход позволяет полностью переписывать внутреннее устройство класса без риска сломать программы, которые уже его используют.
59+
60+
## Сопутствующие темы
61+
- [Object-Oriented Programming](./OOP.md){:.link-accent}
62+
- [Inheritance](./inheritance.md){:.link-accent}
63+
- [Polymorphism](./polymorphism.md){:.link-accent}
64+
- [Abstraction](./abstraction.md){:.link-accent}
65+

docs/python/inheritance.md

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,72 @@
1-
coming soon...
1+
Определение
2+
3+
!!! info ""
4+
**Наследование** (Inheritance) — это принцип ООП, позволяющий создать новый класс на основе уже существующего. Дочерний класс заимствует атрибуты и методы родительского, дополняя или переопределяя их.
5+
6+
## Для чего?
7+
8+
<span class="badge">Наследование</span> систематизирует код, позволяя выстраивать иерархии от общих понятий к более узким. Оно избавляет от ручного копирования функций, формируя базовую логику в одном месте для всех "потомков".
9+
10+
Этот механизм закрепляет принцип <span class="badge">is-a</span> («является»), при котором любой подкласс по умолчанию считается полноценным представителем своего родительского типа.
11+
12+
## Механизмы наследования
13+
14+
Наследование делает классы гибкими и расширяемыми:
15+
16+
- <span class="badge">Переиспользование кода</span> — базовый функционал пишется один раз в родительском классе.
17+
- <span class="badge">Расширение (Extending)</span> — дочерний класс добавляет свои уникальные методы и данные.
18+
- <span class="badge">Переопределение (Overriding)</span> — дочерний класс может изменить поведение метода родителя.
19+
20+
С помощью функции super() дочерний класс может вызвать оригинальную версию метода из родительского класса.
21+
22+
​В Python поддерживается как одиночное, так и множественное наследование:
23+
24+
- <span class="badge">Single Inheritance</span> — классическое наследование от одного предка.
25+
- <span class="badge">Multiple Inheritance</span> — возможность наследоваться от нескольких классов сразу.
26+
- <span class="badge">MRO</span> — Method Resolution Order, порядок, в котором Python ищет методы в иерархии предков.
27+
28+
| Понятие | Суть | Инструмент |
29+
| -------- | ------------------------------------------------- | ------------------------|
30+
| Parent | Базовый класс (суперкласс), от которого наследуют | BaseClass |
31+
| Child | Производный класс (подкласс), который наследует | class Child(BaseClass): |
32+
| super() | Прокси-объект для доступа к методам родителя | super().method() |
33+
34+
Посмотреть порядок поиска методов в сложном дереве наследования можно через атрибут ClassName.__mro__.
35+
## Пример
36+
37+
``` python
38+
class Device:
39+
def __init__(self, brand: str):
40+
self.brand = brand
41+
42+
def turn_on(self):
43+
print(f"{self.brand} включён")
44+
45+
class Smartphone(Device): # Наследование от Device
46+
def __init__(self, brand: str, model: str):
47+
# Вызов конструктора родителя через super()
48+
super().__init__(brand)
49+
self.model = model
50+
51+
def turn_on(self):
52+
# Переопределение метода с сохранением базовой логики
53+
super().turn_on()
54+
print(f"Загрузка системы {self.model}...")
55+
56+
phone = Smartphone("Apple", "iPhone 15")
57+
phone.turn_on()
58+
# Вывод:
59+
# Apple включён
60+
# Загрузка системы iPhone 15...
61+
```
62+
63+
## Ключевые мысли
64+
- Наследование позволяет создавать специализированные классы без повторного написания базовой логики.
65+
- Использование super() критически важно для корректной инициализации всех уровней иерархии, особенно при множественном наследовании.
66+
- Избыточное наследование может сделать код запутанным; иногда лучше использовать композицию (вложение объектов).
67+
68+
## Теги
69+
- [Object-Oriented Programming](./OOP.md){:.link-accent}
70+
- [Encapsulation](./encapsulation.md){:.link-accent}
71+
- [Polymorphism](./polymorphism.md){:.link-accent}
72+
- [Abstraction](./abstraction.md){:.link-accent}

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ plugins:
2828
- search
2929

3030
markdown_extensions:
31+
- tables
3132
- admonition
3233
- attr_list
3334
- pymdownx.highlight

notes/encapsulation.py

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,50 @@
1-
class Router:
2-
# Инициализируем параметры объекта: name и specs.
3-
# self — ссылка на конкретный объект этого класса.
4-
def __init__(self, name, specs):
5-
self.__name = name # Приватные атрибуты
6-
self.__specs = specs
1+
# class Router:
2+
# # Инициализируем параметры объекта: name и specs.
3+
# # self — ссылка на конкретный объект этого класса.
4+
# def __init__(self, name, specs):
5+
# self.__name = name # Приватные атрибуты
6+
# self.__specs = specs
77

8-
# Приватные методы
9-
def __model(self):
10-
return f"Router model: {self.__name}"
8+
# # Приватные методы
9+
# def __model(self):
10+
# return f"Router model: {self.__name}"
1111

12-
def __speed(self):
13-
return f"Router speed: {self.__specs}"
12+
# def __speed(self):
13+
# return f"Router speed: {self.__specs}"
1414

15-
# Публичный метод для вывода полной информации
16-
def hard_specs(self):
17-
return f"{self.__model()}\n{self.__speed()}"
15+
# # Публичный метод для вывода полной информации
16+
# def hard_specs(self):
17+
# return f"{self.__model()}\n{self.__speed()}"
1818

19-
# __ str__ - магический метод, который показывает, как объект класса будет представлен в виде строки
20-
# (например, как ниже после инициализации класса и дальнейшего принта)
21-
def __str__(self):
22-
return f"Router: {self.__name}\nSpecs: {self.__specs}"
19+
# # __ str__ - магический метод, который показывает, как объект класса будет представлен в виде строки
20+
# # (например, как ниже после инициализации класса и дальнейшего принта)
21+
# def __str__(self):
22+
# return f"Router: {self.__name}\nSpecs: {self.__specs}"
2323

2424

25-
r = Router("TP-Link", "1 tb/s")
25+
# r = Router("TP-Link", "1 tb/s")
2626

27-
print(f"__str__ output:\n{r}\n----------------------------") # без __str__ будет: <__main__.router object at 0x74d4076c6780>
27+
# print(f"__str__ output:\n{r}\n----------------------------") # без __str__ будет: <__main__.router object at 0x74d4076c6780>
2828

29-
# Прямой вызов приватного метода вызовет ошибку
30-
# r.__model() # AttributeError
29+
# # Прямой вызов приватного метода вызовет ошибку
30+
# # r.__model() # AttributeError
3131

32-
print(f"Encapsulation (via public method):\n{r.hard_specs()}\n")
32+
# print(f"Encapsulation (via public method):\n{r.hard_specs()}\n")
33+
34+
class Robot:
35+
def __init__(self, model: str):
36+
self.model = model # Публичный: модель робота
37+
self._status = "active" # Защищённый: текущее состояние
38+
self.__core_id = "RX-99" # Приватный: серийный номер ядра
39+
40+
bot = Robot("Wall-E")
41+
42+
# 1. Публичный доступ
43+
print(bot.model) # Wall-E (Работает без ограничений)
44+
45+
# 2. Защищённый (по соглашению)
46+
print(bot._status) # active (Работает, но IDE может выдать предупреждение)
47+
48+
# 3. Приватный (Name Mangling)
49+
# print(bot.__core_id) # Ошибка! AttributeError
50+
print(bot._Robot__core_id) # RX-99 (Доступ через искажённое имя)

0 commit comments

Comments
 (0)