Каковы различия между интерфейсом и абстрактным классом в ООП

Ответ

Основное различие заключается в их назначении: абстрактный класс предоставляет базовую реализацию и общий каркас для наследников (отношение is-a), а интерфейс определяет контракт поведения (набор методов), который класс обязуется выполнить (отношение can-do).

Детальное сравнение

  • Абстрактный класс:

    • Может содержать как абстрактные методы (без реализации), так и обычные методы с реализацией.
    • Может иметь состояние (поля, свойства).
    • Используется для создания иерархии связанных классов с общим функционалом.
    • Класс-наследник расширяет функциональность базового абстрактного класса.
  • Интерфейс:

    • Определяет только сигнатуры методов, без их реализации.
    • Не может иметь состояния (полей).
    • Используется для обеспечения полиморфизма и слабой связности систем.
    • Класс может реализовывать несколько интерфейсов, приобретая различные "способности".

Когда что использовать?

  • Используйте абстрактный класс, если вы хотите предоставить общую, частично реализованную функциональность для группы тесно связанных классов.
  • Используйте интерфейс, если вам нужно определить контракт для классов, которые могут быть не связаны друг с другом, но должны выполнять определенное действие (например, Serializable, Sortable).

Пример на Python

В Python нет формального ключевого слова interface, но эта концепция реализуется с помощью абстрактных базовых классов (abc).

from abc import ABC, abstractmethod

# Интерфейс определяет "что делать" (контракт)
class Flyable(ABC):
    @abstractmethod
    def fly(self):
        pass

# Абстрактный класс определяет "кем быть" и может содержать реализацию
class Animal(ABC):
    def __init__(self, name):
        self.name = name

    @abstractmethod
    def make_sound(self):
        pass

    def sleep(self):
        print(f"{self.name} is sleeping... Zzz")

# Класс реализует интерфейс и наследует абстрактный класс
class Bird(Animal, Flyable):
    def make_sound(self):
        print("Chirp!")

    def fly(self):
        print(f"{self.name} is flying high")

bird = Bird("Sparrow")
bird.make_sound() # Chirp!
bird.fly()        # Sparrow is flying high
bird.sleep()      # Sparrow is sleeping... Zzz