Menu
Coddy logo textTech

Comparable インターフェース

CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 72/110。

== は2つのオブジェクトが等しいかどうかを教えてくれますが、時にはどちらが先に来るかを知る必要がある場合があります。Comparable インターフェースを使用すると、自然な順序を定義することでオブジェクトをソートできるようになります。

クラスを比較可能にするには、Comparable<T>を実装し、compareToメソッドをオーバーライドします。このメソッドは、thisotherより前に来る場合は負の数を、等しい場合はゼロを、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

チャレンジ

簡単

タスクを優先度順にソートできるタスク管理システムを構築しましょう!Comparableインターフェースを実装したTaskクラスを作成し、タスクのリストを優先度の高い順から低い順に自動的にソートできるようにします。

コードを2つのファイルに整理します:

  • task.dart: name (String) と priority (int、数値が高いほど優先度が高い) を持つToDoアイテムを表す Task クラスを作成します。ソートした際にタスクが優先度の降順(優先度が高い順)で表示されるように、Comparable<Task> を実装してください。また、toString() をオーバーライドして、[name] (Priority: [priority]) という形式を返すようにします。
  • main.dart: タスクファイルをインポートし、Comparable インターフェースによって自動ソートがどのように可能になるかを実演します。以下の4つのタスクを含むリストを作成してください:
    • 'Write report' 優先度 2
    • 'Fix critical bug' 優先度 5
    • 'Update documentation' 優先度 1
    • 'Review code' 優先度 3
    Before sorting: と出力し、次に各タスクを出力します。sort() を使用してリストをソートし、空行を出力した後、After sorting: と出力し、続いて各タスクを再度出力します。

Task クラスが Comparable を実装しているため、カスタムの比較関数(comparator)を指定することなく、リストに対して直接 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 メソッドは以下を返します:

  • thisother より前にある場合は負の数
  • 両者が等しい場合は 0
  • thisother より後にある場合は正の数

基本的な実装(昇順):

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 オブジェクトのリストを作成してください:
  // - 優先度 2 の 'Write report'
  // - 優先度 5 の 'Fix critical bug'
  // - 優先度 1 の 'Update documentation'
  // - 優先度 3 の 'Review code'
  
  List<Task> tasks = [
    // TODO: ここに 4 つのタスクを追加してください
  ];
  
  // TODO: "Before sorting:" と出力してください
  // TODO: リスト内の各タスクを出力してください
  
  // TODO: sort() を使用してリストをソートしてください
  
  // TODO: 空行を出力してください
  
  // TODO: "After sorting:" と出力してください
  // TODO: ソートされたリスト内の各タスクを出力してください
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン