Python
Senior
Вопросы ловушки
Ответы
Отлично, сделаем **те же самые ООП-ловушки**, но **максимально просто и на Python**, так как именно так их лучше объяснять **на собеседовании**.
Ниже:
👉 **вопрос → плохой ответ → правильный ответ → простой код**
---
# 1️⃣ «Квадрат — это прямоугольник?»
### ❌ Ловушка
```python
class Rectangle:
def set_width(self, w):
self.w = w
def set_height(self, h):
self.h = h
```
```python
class Square(Rectangle):
def set_width(self, w):
self.w = self.h = w
def set_height(self, h):
self.w = self.h = h
```
```python
def resize(rect):
rect.set_width(5)
rect.set_height(10)
return rect.w * rect.h
```
```python
resize(Rectangle()) # 50
resize(Square()) # 100 ❌
```
### ✅ Вывод
> Наследник **изменил поведение** → нарушен контракт → **нарушение LSP**
---
# 2️⃣ «Зачем нужна композиция, если есть наследование?»
### ❌ Плохо (наследование)
```python
class Engine(Car): # ❌ двигатель — не машина
pass
```
### ✅ Хорошо (композиция)
```python
class Engine:
def start(self):
print("engine started")
class Car:
def __init__(self):
self.engine = Engine()
```
**Ключевая мысль:**
> Если это **has-a**, а не **is-a** → композиция
---
# 3️⃣ «Что такое полиморфизм?»
### ❌ Плохой ответ
> «Это перегрузка методов»
### ✅ Правильный ответ + код
```python
class Cat:
def speak(self):
return "meow"
class Dog:
def speak(self):
return "woof"
```
```python
def make_sound(animal):
print(animal.speak())
```
```python
make_sound(Cat())
make_sound(Dog())
```
👉 **Один интерфейс — разное поведение**
---
# 4️⃣ «Что такое контракт класса?»
### Пример контракта
```python
class BankAccount:
def withdraw(self, amount):
"""
amount > 0
balance >= amount
"""
```
Если наследник нарушает это:
```python
class FakeAccount(BankAccount):
def withdraw(self, amount):
self.balance -= amount * 10 # ❌
```
👉 Контракт нарушен
👉 Полиморфизм сломан
---
# 5️⃣ «Когда наследование — зло?»
### ❌ Хрупкий базовый класс
```python
class Base:
def process(self):
self.step1()
self.step2()
class Child(Base):
def step2(self):
raise Exception("oops")
```
👉 Изменение `Base` может **сломать всех наследников**
---
# 6️⃣ «Инкапсуляция — это private?»
### ❌ Неправильно
```python
class User:
balance = 100 # открыт всем
```
### ✅ Правильно
```python
class User:
def __init__(self):
self._balance = 100
def pay(self, amount):
if amount <= self._balance:
self._balance -= amount
```
> Инкапсуляция = **контроль доступа**, а не просто `_`
---
# 7️⃣ «Что важнее — данные или поведение?»
### ❌ Плохо (анемичная модель)
```python
class Order:
total = 100
```
```python
def apply_discount(order):
order.total *= 0.9
```
### ✅ Хорошо
```python
class Order:
def __init__(self, total):
self.total = total
def apply_discount(self):
self.total *= 0.9
```
👉 **Объект управляет своим состоянием**
---
# 8️⃣ «Можно ли жить без ООП?»
### Да 🙂
```python
def area(width, height):
return width * height
```
👉 Для простых задач **ООП избыточно**
**Правильный ответ:**
> ООП — инструмент, а не обязательство
---
# 9️⃣ «Что такое Бог-объект?»
```python
class SystemManager:
def login(self): ...
def send_email(self): ...
def save_to_db(self): ...
def calculate_salary(self): ...
def render_html(self): ...
```
❌
* нарушен SRP
* сложно тестировать
* сложно поддерживать
---
# 🔟 «Почему композиция лучше наследования?»
### Наследование (жёстко)
```python
class FileLogger(Logger):
...
```
### Композиция (гибко)
```python
class Service:
def __init__(self, logger):
self.logger = logger
```
```python
service = Service(FileLogger())
service = Service(DbLogger())
```
---
# 🧠 Как отвечать на собеседовании (коротко)
Если вопрос кажется простым — говори про:
* **поведение**
* **контракты**
* **is-a vs has-a**
* **LSP**
* **composition over inheritance**
---
## Мини-шпаргалка
```text
is-a → наследование
has-a → композиция
наследник не должен ломать ожидания
ООП = поведение + ответственность
классы ≠ ООП
```
---
Если хочешь, дальше могу:
* разобрать **эти же ловушки на задачах с кодом**
* сделать **чеклист ответов для собеседования**
* разобрать **типичные ошибки Python-разработчиков**
* провести **мок-собеседование**
Скажи, что дальше 👍