В чем разница между implements и extends?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между implements и extends в Dart
Это две разные концепции наследования и реализации интерфейсов в Dart. Хотя они похожи на первый взгляд, они решают разные задачи.
extends — Наследование
extends используется для наследования от класса-родителя. Дочерний класс наследует все свойства и методы родительского класса и может переопределить их.
class Animal {
String name;
Animal(this.name);
void makeSound() {
print('Какой-то звук');
}
void sleep() {
print('$name спит');
}
}
class Dog extends Animal {
String breed;
Dog(String name, this.breed) : super(name);
@override
void makeSound() {
print('Гав-гав!');
}
void fetchBall() {
print('$name принёс мяч');
}
}
void main() {
var dog = Dog('Бобик', 'Лабрадор');
dog.makeSound(); // Гав-гав!
dog.sleep(); // Бобик спит (наследованный метод)
dog.fetchBall(); // Бобик принёс мяч
}
Характеристики extends:
- Наследует все методы и свойства от родителя
- Может использовать родительские методы через super
- Иерархия классов (is-a отношение)
- Может быть только один родительский класс
- Полиморфизм через переопределение методов
implements — Реализация интерфейса
implements используется для реализации контракта (интерфейса). Класс должен реализовать все методы и свойства интерфейса, но НЕ наследует их реализацию.
abstract class Animal {
void makeSound();
void eat();
}
class Dog implements Animal {
String name;
Dog(this.name);
@override
void makeSound() {
print('Гав-гав!');
}
@override
void eat() {
print('$name ест мясо');
}
void fetchBall() {
print('$name принёс мяч');
}
}
class Bird implements Animal {
String name;
Bird(this.name);
@override
void makeSound() {
print('Чирик-чирик!');
}
@override
void eat() {
print('$name клюёт зёрна');
}
void fly() {
print('$name летает');
}
}
void main() {
Animal dog = Dog('Бобик');
Animal bird = Bird('Чик');
dog.makeSound(); // Гав-гав!
bird.makeSound(); // Чирик-чирик!
dog.eat(); // Бобик ест мясо
bird.eat(); // Чик клюёт зёрна
}
Характеристики implements:
- Класс обязан реализовать все методы интерфейса
- НЕ наследует реализацию, только сигнатуру
- Можно реализовать несколько интерфейсов одновременно
- Определяет контракт (что должно быть, но не как)
- Позволяет полиморфизм без иерархии
Сравнительная таблица
| Аспект | extends | implements |
|---|---|---|
| Тип | Наследование | Реализация интерфейса |
| Наследует реализацию | Да | Нет |
| Наследует сигнатуру | Да | Да |
| Количество | Один класс | Несколько интерфейсов |
| Иерархия | Есть (is-a) | Нет |
| super доступен | Да | Нет |
| Использование | Переиспользование кода | Определение контракта |
Практический пример
// Интерфейс — контракт
abstract class PaymentProcessor {
void processPayment(double amount);
bool refund(double amount);
}
// Базовый класс с реализацией
class BasePaymentProcessor {
void logTransaction(String message) {
print('[LOG] $message');
}
}
// Класс, который и наследует, и реализует
class CreditCardProcessor extends BasePaymentProcessor implements PaymentProcessor {
String cardNumber;
CreditCardProcessor(this.cardNumber);
@override
void processPayment(double amount) {
logTransaction('Обработка платежа $amount на карту $cardNumber');
print('Платёж принят!');
}
@override
bool refund(double amount) {
logTransaction('Возврат $amount на карту $cardNumber');
return true;
}
}
class PayPalProcessor implements PaymentProcessor {
String email;
PayPalProcessor(this.email);
@override
void processPayment(double amount) {
print('Отправка платежа $amount на $email через PayPal');
}
@override
bool refund(double amount) {
print('Возврат через PayPal');
return true;
}
}
void main() {
PaymentProcessor creditCard = CreditCardProcessor('1234-5678-9012-3456');
PaymentProcessor paypal = PayPalProcessor('user@example.com');
creditCard.processPayment(100); // Полиморфизм
paypal.processPayment(50);
}
Когда использовать extends
✅ Есть общая реализация кода ✅ is-a отношение (Собака IS-A Животное) ✅ Переиспользование кода ✅ Иерархия классов
Когда использовать implements
✅ Определение контракта ✅ Разные способы реализации одного интерфейса ✅ Несколько источников функциональности ✅ Loose coupling между классами
Множественная реализация
Важное отличие Dart: в Dart можно реализовать несколько интерфейсов (implements), но наследовать можно только от одного класса (extends).
class Dog extends Animal implements Comparable, Runnable {
// Наследует от Animal
// Реализует интерфейсы Comparable и Runnable
}
Заключение
extends используется когда нужно переиспользовать код и создать иерархию классов. implements используется когда нужно определить контракт, который разные классы могут реализовать по-своему. На практике часто используют оба: наследование для переиспользования кода и интерфейсы для определения контрактов.