В чем разница между `implements` и `extends` в Dart?

Ответ

В Dart extends и implements служат для разных целей наследования и реализации.

extends (наследование класса)

Используется для создания подкласса. Новый класс наследует все поля и методы родительского класса (и абстрактные, и реализованные). Поддерживает только одиночное наследование.

class Animal {
  void breathe() => print('Breathing...');
}

class Dog extends Animal {
  void bark() => print('Woof!');
  // Наследует метод breathe()
}

void main() {
  var dog = Dog();
  dog.breathe(); // Вывод: Breathing...
  dog.bark();    // Вывод: Woof!
}

implements (реализация интерфейса)

Обязывает класс предоставить собственную реализацию всех публичных членов (полей и методов) другого класса или интерфейса. Позволяет реализовать несколько интерфейсов.

abstract class Flyable {
  void fly();
}

abstract class Swimmable {
  void swim();
}

class Duck implements Flyable, Swimmable {
  @override
  void fly() => print('Duck is flying');

  @override
  void swim() => print('Duck is swimming');
}

Ключевое отличие:

  • extends — это отношение "является" (Dog является Animal). Вы получаете готовую реализацию.
  • implements — это отношение "ведёт себя как" (Duck ведёт себя как Flyable и Swimmable). Вы обязуетесь предоставить свою реализацию контракта.

Ответ 18+ 🔞

Слушай, а вот эта вся история с extends и implements — это, блядь, классика, хуй с горы. Представь себе такую картину.

Вот есть у тебя класс Animal. Ну, типа, базовый, старый, как говно мамонта. У него метод breathe() — дышит себе и дышит, ядрёна вошь. Так вот, когда ты пишешь class Dog extends Animal, ты, по сути, заявляешь: «Слушай, этот пёс — он является животным. Всё, что умеет животное, он умеет по умолчанию, ебать копать». Он дышит, потому что его батя дышал. Ты просто берёшь и наследуешь всё, как есть, и можешь добавить свою фишку — bark(). Это как взять дедовский «Москвич», отмыть его от говна, но под капотом всё то же самое, только ты прикрутил новую магнитолу, которая орет «Группа крови». Вот и вся магия. И наследоваться так можно только от одного класса — потому что у машины, блядь, один руль, а не три. Иначе это уже пиздопроебибна какая-то.

А теперь смотри сюда, чувак. Вот есть интерфейс Flyable. Это не класс, это, типа, контракт. Бумажка, на которой написано: «Все, кто под этим подпишется, обязуются уметь летать. Точка». И есть Swimmable — аналогичная бумажка про плавание.

Когда ты пишешь class Duck implements Flyable, Swimmable, ты не наследуешь нихуя! Ты говоришь: «Я, утка, веду себя как летающий объект и как плавающий объект. Я обязуюсь предоставить свои, утиные, реализации методов fly() и swim()». Это как если бы ты пришёл устраиваться на две работы сразу: и курьером, и сантехником. Тебе не дают готовый велосипед и разводной ключ — тебе говорят: «Хорошо, чувак, но свой велосипед и свой ключ ты принесешь сам, и работать будешь по нашему графику». И ты, такой, «окей», и сам пишешь, как именно твоя утка летает и плавает. И таких контрактов ты можешь взять овердохуища — лишь бы сил хватило все методы реализовать.

Короче, суть, чтобы ты совсем не бздел:

  • extends — это «я твой сын, папа, дай твои гены и тачку». Получаешь всё готовое, но привязан к одному предку.
  • implements — это «я независимый мужик, я сам всё умею, просто дайте мне список требований». Ничего готового не получаешь, но можешь подписать кучу контрактов и сделать всё по-своему.

Вот и вся разница, ёпта. Выбирай, что тебе больше подходит: быть наследником с готовым наследством, но в рамках одной семьи, или вольным художником, который сам за всё отвечает, но может работать на кого угодно.