Интерфейс Comparable
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 72 из 110.
В то время как == сообщает вам, равны ли два объекта, иногда вам нужно знать, какой из них идет первым. Интерфейс Comparable позволяет сортировать ваши объекты, определяя естественный порядок.
Чтобы сделать класс сравнимым, реализуйте Comparable<T> и переопределите метод compareTo. Этот метод возвращает отрицательное число, если this идет перед other, ноль, если они равны, и положительное число, если this идет после:
class Student implements Comparable<Student> {
String name;
int grade;
Student(this.name, this.grade);
@override
int compareTo(Student other) {
return grade.compareTo(other.grade);
}
}
void main() {
var students = [
Student('Alice', 85),
Student('Bob', 92),
Student('Carol', 78),
];
students.sort();
for (var s in students) {
print('${s.name}: ${s.grade}');
}
// Carol: 78, Alice: 85, Bob: 92
}Как только ваш класс реализует Comparable, вы сможете использовать sort() без предоставления пользовательского компаратора. Встроенные числовые и строковые типы уже реализуют Comparable, вот почему grade.compareTo(other.grade) работает напрямую.
Для сортировки по убыванию просто измените порядок сравнения на обратный, поменяв объекты местами или инвертировав результат:
@override
int compareTo(Student other) {
return other.grade.compareTo(grade); // По убыванию
}Задание
ЛегкоДавайте создадим систему управления задачами, в которой задачи можно сортировать по уровню их приоритета! Вы создадите класс Task, который реализует интерфейс Comparable, что позволит автоматически сортировать список задач от самого высокого до самого низкого приоритета.
Вы организуете свой код в двух файлах:
task.dart: Создайте классTask, который представляет элемент списка дел с полямиname(String) иpriority(int, где большие числа означают более высокий приоритет). Ваш класс должен реализовыватьComparable<Task>так, чтобы при сортировке задачи располагались в порядке убывания приоритета (сначала самый высокий приоритет). Также переопределитеtoString(), чтобы он возвращал формат:[name] (Priority: [priority])main.dart: Импортируйте файл с задачами и продемонстрируйте, как интерфейсComparableобеспечивает автоматическую сортировку. Создайте список, содержащий следующие четыре задачи:'Write report'с приоритетом2'Fix critical bug'с приоритетом5'Update documentation'с приоритетом1'Review code'с приоритетом3
Before sorting:, затем выведите каждую задачу. Отсортируйте список с помощьюsort(), выведите пустую строку, затем выведитеAfter sorting:и снова каждую задачу.
Поскольку ваш класс Task реализует Comparable, вы можете вызывать sort() непосредственно для списка без предоставления пользовательского компаратора. Задачи автоматически упорядочатся на основе вашей реализации compareTo!
Ожидаемый вывод:
Before sorting:
Write report (Priority: 2)
Fix critical bug (Priority: 5)
Update documentation (Priority: 1)
Review code (Priority: 3)
After sorting:
Fix critical bug (Priority: 5)
Review code (Priority: 3)
Write report (Priority: 2)
Update documentation (Priority: 1)Шпаргалка
Интерфейс Comparable позволяет объектам определять естественный порядок сортировки. Реализуйте Comparable<T> и переопределите метод compareTo.
Метод compareTo возвращает:
- Отрицательное число, если
thisстоит передother - Ноль, если они равны
- Положительное число, если
thisстоит послеother
Базовая реализация (по возрастанию):
class Student implements Comparable<Student> {
String name;
int grade;
Student(this.name, this.grade);
@override
int compareTo(Student other) {
return grade.compareTo(other.grade);
}
}Как только класс реализует Comparable, вы можете использовать sort() без пользовательского компаратора:
var students = [
Student('Alice', 85),
Student('Bob', 92),
Student('Carol', 78),
];
students.sort(); // Автоматически использует compareToДля сортировки по убыванию измените порядок сравнения на обратный:
@override
int compareTo(Student other) {
return other.grade.compareTo(grade); // По убыванию
}Попробуйте сами
import 'task.dart';
void main() {
// TODO: Создайте список объектов Task со следующими данными:
// - 'Write report' с приоритетом 2
// - 'Fix critical bug' с приоритетом 5
// - 'Update documentation' с приоритетом 1
// - 'Review code' с приоритетом 3
List<Task> tasks = [
// TODO: Добавьте сюда четыре задачи
];
// TODO: Выведите "Before sorting:"
// TODO: Выведите каждую задачу из списка
// TODO: Отсортируйте список, используя sort()
// TODO: Выведите пустую строку
// TODO: Выведите "After sorting:"
// TODO: Выведите каждую задачу из отсортированного списка
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыБиблиотеки и импортВведение в ООПКлассы и объектыКлючевое слово thisМетодыПеременные экземпляраОсновы конструкторовИтоги — Простой калькулятор4Null-безопасность
Введение в Null-безопасностьNullable и Non-Nullable типыОператоры ? и !Ключевое слово Late и Null-безопасностьNull-aware операторыNull-безопасность в классахИтоги — Система профилей пользователей7Абстрактные классы и интерфейсы
Абстрактные классыАбстрактные методыИнтерфейсы в DartНеявные интерфейсыРеализация против наследованияМножественные интерфейсыИтоги — Калькулятор фигур10Коллекции и обобщения
Обзор List, Set, MapТипобезопасные коллекцииОбобщенные классыОбобщенные методыОграничения обобщенийIterable и IteratorИтоги: Обобщенное хранилище13Продвинутые концепции ООП
Композиция против наследованияМетоды расширенияВызываемые классыЗапечатанные классы (Dart 3)Записи (Dart 3)Паттерны и сопоставление (3.0)Перечисления с методами16Проект: Управление библиотекой
Обзор проектаКлассы Book и User2Конструкторы в Dart
Конструктор по умолчаниюИменованные конструкторыСписки инициализацииКонстантные конструкторыФабричные конструкторыПеренаправляющие конструкторыИтоги — Shape Builder5Инкапсуляция
Публичные и приватные членыСоглашение о префиксе _Приватность на уровне библиотекГеттеры и сеттеры: подробный разборСкрытие данныхИтоги — Записи о студентах8Mixins
Введение в MixinsСоздание MixinsИспользование нескольких MixinsКлючевое слово on в MixinsMixin и наследованиеMixin и интерфейсИтоги: Система животных11Специальные методы
Переопределение toString()Переопределение hashCode и ==Интерфейс ComparableМетод call()Переопределение noSuchMethodПовторение — Пользовательская коллекция14Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy3Свойства классов
Члены экземпляра и статические членыПоля Final и ConstПеременные LateСтатические методы и поляГеттеры и сеттерыИтоги — Менеджер банковского счета6Наследование
Основы наследованияКлючевое слово superПереопределение методовАннотация @overrideКлючевое слово final для классовКонструкторы и наследованиеИтоги: Иерархия сотрудников9Полиморфизм
Основы полиморфизмаПолиморфизм через интерфейсыПроверка типов во время выполненияОператоры is и asКлючевое слово covariantИтоги — Обработчик платежей12Асинхронное ООП
Futures и async/awaitОсновы StreamsКонтроллеры StreamАсинхронные конструкторыАсинхронность в методах классовИтоги — Data Fetcher15Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий