Object-Oriented Programming

Четыре кита ООП + практика

Основные принципы ООП

Inheritance, Polymorphism, Abstraction, Encapsulation

1. Inheritance (Наследование)

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

🔹 Общее поведение — в базовом классе

2. Polymorphism

def make_animal_speak(animal: Animal):
    print(animal.speak())

make_animal_speak(Dog())  # Woof!
make_animal_speak(Cat())  # Meow!

🔹 Один интерфейс — разное поведение

3. Abstraction

from abc import ABC, abstractmethod

class Model(ABC):
    @abstractmethod
    def train(self): pass

    @abstractmethod
    def predict(self): pass

# Не можешь создать экземпляр без реализации
class NeuralNet(Model):
    def train(self): ...
    def predict(self): ...

4. Encapsulation

class BankAccount:
    def __init__(self):
        self._balance = 0  # защищённое

    def deposit(self, amount):
        if amount > 0:
            self._balance += amount

    def get_balance(self):
        return self._balance  # контролируем доступ

🔹 Скрытие деталей реализации

Возможности парадигмы

Abstract vs Concrete Classes

# Абстрактный — не создаётся
class Service(ABC):
    @abstractmethod
    def run(self): pass

# Конкретный — можно создать
class TrainingService(Service):
    def run(self):
        print("Training started")

Interfaces

class Storable(ABC):
    @abstractmethod
    def save(self): pass

class JSONStorable(Storable):
    def save(self):
        write_json(self.data)

class DBStorable(Storable):
    def save(self):
        db.save(self.record)

🔹 Клиент зависит от интерфейса, а не от реализации

Scope / Visibility

class User:
    def __init__(self, name):
        self.name = name        # public
        self._temp_token = ""   # protected (по соглашению)
        self.__secret = "..."   # private (name mangling)

🔹 `public`, `_protected`, `__private`

Model-Driven Design

Код как отражение предметной области

Domain Models

class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

class Order:
    def __init__(self, user: User, amount):
        self.user = user
        self.amount = amount

🔹 Модели соответствуют реальным сущностям

Layered Architectures

presentation/
  ├── api.py
application/
  ├── usecases.py
domain/
  ├── models.py
  └── services.py
infrastructure/
  ├── database.py
  └── email_client.py

🔹 Границы ответственности

Anemic Models (Опасность!)

class User:
    def __init__(self):
        self.name = ""
        self.email = ""

# А вся логика — где-то в другом месте
def validate_user(user):
    return '@' in user.email

❌ Модель без поведения — плохая инкапсуляция

✅ Rich Models

class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

    def is_valid(self):
        return '@' in self.email

    def upgrade_to_premium(self):
        self.role = "premium"
        self.send_welcome_email()

✔️ Логика рядом с данными