Ответ
В 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— это «я независимый мужик, я сам всё умею, просто дайте мне список требований». Ничего готового не получаешь, но можешь подписать кучу контрактов и сделать всё по-своему.
Вот и вся разница, ёпта. Выбирай, что тебе больше подходит: быть наследником с готовым наследством, но в рамках одной семьи, или вольным художником, который сам за всё отвечает, но может работать на кого угодно.