Menu
Coddy logo textTech

Аннотация @override

Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 39 из 110.

Аннотация @override — это маркер передовой практики, который сообщает Dart (и другим разработчикам), что вы намеренно заменяете метод родительского класса. Хотя переопределение методов работает и без неё, использование @override создает важную подстраховку.

class Animal {
  String name;
  
  Animal(this.name);
  
  void speak() {
    print('$name makes a sound');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);
  
  @override
  void speak() {
    print('$name barks: Woof!');
  }
}

Аннотация дает два ключевых преимущества. Во-первых, она четко документирует ваше намерение — любой, кто читает код, сразу понимает, что этот метод существует в родительском классе. Во-вторых, анализатор Dart предупредит вас, если родительский метод на самом деле не существует, что позволяет на ранней стадии обнаружить опечатки и ошибки рефакторинга.

Рассмотрим, что произойдет, если вы неправильно напишете имя метода без @override:

class Cat extends Animal {
  Cat(String name) : super(name);
  
  void speek() {  // Опечатка! Нет предупреждения без @override
    print('$name meows');
  }
}

Без аннотации Dart предполагает, что вы создаете новый метод с именем speek(). С @override анализатор немедленно сообщит о том, что такого метода не существует в родительском классе. Эта простая аннотация предотвращает неявные ошибки, которые может быть трудно отследить позже.

challenge icon

Задание

Легко

Давайте создадим систему медиаплеера, которая продемонстрирует важность аннотации @override при настройке унаследованного поведения. Вы создадите различные типы медиа, каждый из которых воспроизводит контент по-своему.

Вы организуете свой код в два файла:

  • media.dart: Определите здесь иерархию медиа:
    • Класс Media со свойством String title, конструктором, принимающим заголовок, и методом play(), который выводит Playing: [title]
    • Класс Song, который расширяет Media и добавляет свойство String artist. Используйте аннотацию @override и переопределите play(), чтобы вывести Playing song: [title] by [artist]
    • Класс Video, который расширяет Media и добавляет свойство int duration (в секундах). Используйте @override и переопределите play(), чтобы сначала вызвать родительскую версию с помощью super.play(), а затем вывести Duration: [duration] seconds
  • main.dart: Импортируйте файл медиа и продемонстрируйте переопределенные методы:
    • Создайте объект Media с заголовком 'Generic Content' и вызовите play()
    • Выведите пустую строку
    • Создайте Song с заголовком 'Imagine' и исполнителем 'John Lennon', затем вызовите play()
    • Выведите пустую строку
    • Создайте Video с заголовком 'Dart Tutorial' и длительностью 360, затем вызовите play()

Аннотация @override документирует ваше намерение и помогает отлавливать ошибки. Если вы случайно напишете play() как plya(), аннотация предупредит вас о том, что такого метода в родительском классе не существует.

Ожидаемый вывод:

Playing: Generic Content

Playing song: Imagine by John Lennon

Playing: Dart Tutorial
Duration: 360 seconds

Шпаргалка

Аннотация @override помечает методы, которые намеренно заменяют метод родительского класса. Хотя она необязательна, она обеспечивает безопасность и ясность.

class Animal {
  String name;
  
  Animal(this.name);
  
  void speak() {
    print('$name makes a sound');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);
  
  @override
  void speak() {
    print('$name barks: Woof!');
  }
}

Преимущества @override:

  • Документирует намерение — показывает, что метод существует в родительском классе
  • Отлавливает ошибки — анализатор Dart выдает предупреждение, если родительский метод не существует, предотвращая опечатки

Без @override опечатки создают новые методы вместо того, чтобы сигнализировать об ошибках:

class Cat extends Animal {
  Cat(String name) : super(name);
  
  void speek() {  // Опечатка создает новый метод без предупреждения
    print('$name meows');
  }
}

Вы можете вызвать версию родителя, используя super:

@override
void play() {
  super.play();  // Сначала вызываем родительский метод
  print('Additional behavior');
}

Попробуйте сами

import 'media.dart';

void main() {
  // TODO: Создайте объект Media с заголовком 'Generic Content' и вызовите play()
  
  
  // TODO: Выведите пустую строку
  
  
  // TODO: Создайте объект Song с заголовком 'Imagine' и исполнителем 'John Lennon', затем вызовите play()
  
  
  // TODO: Выведите пустую строку
  
  
  // TODO: Создайте объект Video с заголовком 'Dart Tutorial' и длительностью 360, затем вызовите play()
  
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование