Menu
Coddy logo textTech

Интерфейс 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);  // По убыванию
}
challenge icon

Задание

Легко

Давайте создадим систему управления задачами, в которой задачи можно сортировать по уровню их приоритета! Вы создадите класс 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: Выведите каждую задачу из отсортированного списка
}
quiz iconПроверьте себя

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

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