dartooptostringMenengah4 mnt baca

Override toString & Equality

Membuat objek tampil bermakna dan perbandingan == yang benar.

Objek yang bisa menjelaskan dirinya

Coba print objek custom: keluar Instance of 'Siswa', tidak informatif. Override toString mengganti tampilan default itu dengan representasi bermakna. Override == memperbaiki perbandingan: default-nya membandingkan identitas (apakah objek yang sama persis), padahal sering kamu ingin membandingkan nilai.

Analogi: toString itu seperti papan nama di dada. == default itu seperti sidik jari (identitas unik). Kadang kamu butuh membandingkan KTP (nilai): dua KTP berbeda tapi data sama = orang yang sama.

Kenapa override ini penting?

Tiga alasan: debugging (log bermakna vs Instance of), kebenaran logika (dua objek bernilai sama dianggap sama), dan koleksi (Set/Map memakai == dan hashCode untuk duplikat/kunci).

Override toString

dart
class Siswa {
  String nama;
  int nilai;
  Siswa(this.nama, this.nilai);

  @override
  String toString() => 'Siswa(nama: $nama, nilai: $nilai)';
}

void main() {
  var s = Siswa('Budi', 85);
  print(s); // Siswa(nama: Budi, nilai: 85), bukan Instance of 'Siswa'!

  var daftar = [Siswa('Ani', 90), Siswa('Cici', 75)];
  print(daftar); // [Siswa(nama: Ani, nilai: 90), Siswa(nama: Cici, nilai: 75)]
}

Satu baris mengubah semua print, log, dan debug menjadi bermakna. Kebiasaan wajib untuk setiap class data.

Override == dan hashCode

dart
class Koordinat {
  final int x;
  final int y;
  const Koordinat(this.x, this.y);

  @override
  bool operator ==(Object lain) {
    if (identical(this, lain)) return true; // objek sama persis
    return lain is Koordinat && lain.x == x && lain.y == y;
  }

  @override
  int get hashCode => Object.hash(x, y);

  @override
  String toString() => '($x, $y)';
}

void main() {
  var a = Koordinat(3, 4);
  var b = Koordinat(3, 4);
  print(a == b); // true! (tanpa override: false)

  var set = {a};
  print(set.contains(b)); // true, berkat == + hashCode
}

Aturan emas: == dan hashCode selalu berpasangan. Jika dua objek == maka hashCode-nya HARUS sama. Melanggar ini merusak Set dan Map (duplikat lolos, kunci hilang).

Contoh kedua, pola yang lebih ringkas:

dart
class Produk {
  final String kode;
  final String nama;
  const Produk(this.kode, this.nama);

  @override
  bool operator ==(Object lain) =>
      identical(this, lain) ||
      (lain is Produk && lain.kode == kode);

  @override
  int get hashCode => kode.hashCode;

  @override
  String toString() => 'Produk($kode: $nama)';
}

void main() {
  var p1 = Produk('A1', 'Laptop');
  var p2 = Produk('A1', 'Laptop Gaming'); // nama beda, kode sama
  print(p1 == p2); // true: identitas produk = kodenya
}

Pilih field yang menjadi identitas (kode), bukan semua field. Dua produk dengan kode sama = produk sama walau nama tampilan beda.

Kesalahan umum

1. Override == tanpa hashCode

dart
// SALAH: Set/Map rusak
class A {
  final int x;
  A(this.x);
  @override
  bool operator ==(Object o) => o is A && o.x == x;
  // hashCode tidak di-override!
}

void main() {
  var s = {A(1)};
  print(s.contains(A(1))); // false! (seharusnya true)
}

Selalu override keduanya. Object.hash(x, y) adalah cara modern menggabung hash.

2. == tidak menangani tipe lain

dart
// SALAH: crash jika dibandingkan tipe lain
// bool operator ==(Object o) => (o as Koordinat).x == x;
dart
// BENAR: cek tipe dulu dengan 'is'
@override
bool operator ==(Object lain) =>
    identical(this, lain) ||
    (lain is Koordinat && lain.x == x && lain.y == y);

3. toString yang terlalu panjang

toString untuk debugging: ringkas satu baris. Jangan masukkan list 1000 elemen ke toString.

Kesimpulan

Override toString untuk semua class data (debugging bermakna). Override == + hashCode berpasangan saat butuh kesetaraan nilai (Set, Map, perbandingan). Pilih field identitas dengan bijak.

Catatan teknis: Package equatable mengotomatiskan == dan hashCode: class K extends Equatable { List<Object?> get props => [x, y]; }. Standar di proyek Flutter besar.

Tantangan

Kartu anggota

Buat class Anggota (nama, id) dengan toString 'Anggota(Budi #101)' dan == berdasarkan id saja. Buktikan: dua objek nama beda tapi id sama dianggap ==, dan Set menolak duplikat id.

text
class Anggota {
  String nama;
  int id;
  Anggota(this.nama, this.id);
  // TODO: toString, ==, hashCode
}

void main() {
  var a = Anggota('Budi', 101);
  var b = Anggota('Budi Santoso', 101);
  // TODO: buktikan a == b true, dan Set hanya berisi 1
}

Kuis Bab

Uji pemahamanmu: Bab 4: OOP di Dart

Jawab 5 soal berikut, lalu tekan "Periksa Jawaban".

1.Apa output dari: class K { String nama; K(this.nama); } void main() { print(K('Budi').nama); }

2.Apa itu named constructor di Dart?

3.Keyword apa yang dipakai agar sebuah class mewarisi class lain di Dart?

4.Bisakah abstract class diinstansiasi langsung dengan new (constructor)?

5.Bagaimana cara memakai mixin di Dart?