I. Apa itu Record?
Record adalah tipe agregat anonim dan tidak dapat diubah, berfungsi untuk menggabungkan beberapa data dengan tipe berbeda menjadi satu objek. Berikut perbedaan utama dengan List / Set / Map:
- Panjang tetap: setelah dibuat, jumlah field tidak bisa ditambah atau dikurangi, penyimpanan heterogen:
- Satu Record dapat menampung tipe data yang berbeda total seperti int, String, bool
- Batasan tipe kuat: kompiler mengenali tipe setiap field, keamanan tipe tidak hilang
- Hanya baca, tidak bisa diubah: nilai field tidak dapat ditetapkan ulang setelah pembuatan
Record adalah variabel valid penuh, mendukung semua operasi umum: disimpan di variabel, dikirim sebagai parameter / nilai balik banyak fungsi, bersarang, dimasukkan ke List/Map/Set.
II. Sintaks Dasar Record
1. Literal Record
Dibungkus kurung bulat, dipisah koma, terbagi dua kategori: field posisi dan field bernama. Field posisi ditulis di depan, field bernama mengikuti dengan sintaks kunci:.
// Campuran field posisi + field bernama
var info = ('Jim', age: 20, flag: true, 'Student');Code language: JavaScript (javascript)
2. Cara Penggunaan Record
1 Field Posisi
// Deklarasi: dua field posisi, urutan String, int
(String, int) user;
// Penugasan menyesuaikan struktur
user = ('李四', 22);
Code language: JavaScript (javascript)
2 Field Bernama
Deklarasi tipe menggunakan kurung kurawal {}
// Deklarasi dua field bernama a(int), b(bool)
({int a, bool b}) data;
data = (a: 100, b: false);Code language: JavaScript (javascript)
3 Penggunaan Campuran
Deklarasi tipe gabungan field posisi dan field bernama
// 1 field posisi String, 2 field bernama score(int), pass(bool)
(String, {int score, bool pass}) exam;
exam = ('Ujian Akhir', score: 90, pass: true);
Code language: JavaScript (javascript)
III. Kesalahan Umum
1: Nama field bernama merupakan bagian struktur tipe; nama berbeda menghasilkan tipe yang benar-benar berbeda
// Tipe: ({int a, int b})
({int a, int b}) pointAB = (a: 1, b: 2);
// Tipe: ({int x, int y})
({int x, int y}) pointXY = (x: 3, y: 4);
// Error kompilasi! Tipe tidak cocok, tidak boleh saling tetapkan nilai
// pointAB = pointXY;
Code language: JavaScript (javascript)
Untuk field bernama, meskipun keduanya dua nilai int, nama ab dan xy berbeda sehingga tidak bisa saling tetapkan. Lihat bagian bawah untuk field posisi.
2: Alias pada field posisi di anotasi tipe hanya komentar, tidak berpengaruh pada pencocokan tipe
Nama yang diberikan ke field posisi di dalam kurung hanya dokumentasi untuk pengembang, diabaikan kompiler. Jika struktur sama, penugasan diizinkan:
(int a, int b) p1 = (10, 20);
(int x, int y) p2 = (30, 40);
// Valid, di balik layar dua field posisi int, tipe identik
p1 = p2;Code language: JavaScript (javascript)
Analogi parameter fungsi: mengganti nama parameter tidak mengubah tanda tangan fungsi, logikanya sama.
IV. Membaca Field Internal Record
Record bersifat tidak dapat diubah, hanya ada getter tanpa setter, nilai field tidak bisa diubah.
- Field bernama: akses langsung pakai
.namaField - Field posisi: akses pakai
$angka; angka melewati semua field bernama dan hanya menghitung urutan field posisi
var record = ('first', a: 2, b: true, 'last');
print(record.$1); // Field posisi pertama: first
print(record.a); // Field bernama a: 2
print(record.b); // Field bernama b: true
print(record.$2); // Field posisi kedua: last
Code language: PHP (php)
V. Aturan Penentuan Tipe Struktur Record
Record tidak butuh definisi class terpisah; tipe ditentukan berdasarkan bentuk struktur:
Bentuk = total jumlah field + tipe setiap field + nama field bernama
Jika bentuk sama persis, meskipun berasal dari file atau library berbeda, termasuk tipe yang sama.
Kompiler mengenali tipe statis setiap field secara terus-menerus, tidak ada kehilangan informasi tipe:
// Posisi 1 tipe num, posisi 2 tipe Object
(num, Object) pair = (42, 'Sebuah teks');
var firstVal = pair.$1; // Tipe statis num, saat runtime int
var secondVal = pair.$2;// Tipe statis Object, saat runtime StringCode language: JavaScript (javascript)
VI. Perbandingan Kesamaan Record ==
Dua syarat agar dua Record dinyatakan sama:
- Kedua Record memiliki bentuk struktur yang sama persis
- Semua nilai field posisi / bernama yang bersesuaian sama
Urutan penulisan field bernama tidak mempengaruhi perbandingan kesamaan; namun nama field yang berbeda berarti tipe berbeda dan pasti tidak sama.
// Field posisi, bentuk sama dan nilai cocok → true
(int x, int y, int z) point = (1, 2, 3);
(int r, int g, int b) color = (1, 2, 3);
print(point == color); // true
// Nama field bernama berbeda, tipe tidak sama → false
({int x, int y, int z}) p = (x:1, y:2, z:3);
({int r, int g, int b}) c = (r:1, g:2, b:3);
print(p == c); // falseCode language: PHP (php)
Record secara otomatis menimpa operator == dan metode hashCode, tidak perlu implementasi manual.
VII. Nilai Balik Banyak Fungsi
Fungsi Dart hanya bisa mengembalikan satu nilai. Gunakan Record untuk menggabungkan berbagai tipe data, padukan dengan destrukturasi pola untuk memisahkan cepat menjadi variabel mandiri; pengganti sempurna List/Map (tanpa kehilangan keamanan tipe).
1 Destrukturasi Field Posisi
// Kembalikan: Nama(String), Umur(int)
(String name, int age) getUserInfo(Map<String, dynamic> json) {
return (json['name'] as String, json['age'] as int);
}
void main() {
final userJson = {'name': 'Dash', 'age': 10, 'color': 'blue'};
// Destrukturasi langsung, dua variabel satu baris
var (userName, userAge) = getUserInfo(userJson);
print(userName); // Dash
print(userAge); // 10
}
Code language: JavaScript (javascript)
2 Destrukturasi Field Bernama
Sintaks :namaField
({String name, int age}) getUserInfo(Map<String, dynamic> json) {
return (name: json['name'] as String, age: json['age'] as int);
}
void main() {
final userJson = {'name': 'Dash', 'age': 10};
// Sintaks destrukturasi bernama
final (:name, :age) = getUserInfo(userJson);
print(name);
}
Code language: JavaScript (javascript)
Kekurangan Alternatif Lain
Di bahasa lain seperti C++, C#, Java tanpa Record perlu lakukan langkah berikut:
- Buat class baru: kode berlebih, harus tulis konstruktor dan field;
- Kembalikan pakai List: hilang keamanan tipe, semua jadi dynamic;
- Kembalikan pakai Map: kunci mudah salah ketik, tidak ada validasi tipe statis.
VIII. Data Terstruktur Ringan
Jika hanya butuh simpan data tanpa metode, gunakan langsung Record tanpa buat class baru. Menghapus kode berlebih pendeklarasian class, cocok untuk daftar data massal.
Contoh
Daftar konfigurasi tombol halaman (contoh Flutter, akan paham setelah belajar Flutter)
import 'package:flutter/material.dart';
void main() {
final buttonList = [
(
label: "Unggah Berkas",
icon: const Icon(Icons.upload_file),
onPressed: () => print("Tombol unggah diklik"),
),
(
label: "Lihat Detail",
icon: const Icon(Icons.info),
onPressed: () => print("Tombol detail diklik"),
)
];
}
Code language: JavaScript (javascript)
IX. typedef: Alias Tipe untuk Record
Sederhanakan tipe yang panjang
Deklarasi tipe Record biasanya panjang. Gunakan typedef buat alias tipe agar mudah dipakai ulang dan mudah ubah struktur field secara seragam nantinya.
Penggunaan Dasar
// Buat alias Record tombol, onPressed boleh null
typedef ButtonConfig = ({
String label,
Icon icon,
void Function()? onPressed
});
// Deklarasi daftar langsung pakai alias
List<ButtonConfig> buttons = [
(label: "Kirim", icon: const Icon(Icons.check), onPressed: () {}),
(label: "Batal", icon: const Icon(Icons.close), onPressed: null),
];
Code language: PHP (php)
Pengembangan Selanjutnya
Jika nanti perlu tambah metode atau logika ke data, tidak usah ubah kode perulangan bisnis: hanya ganti tipe saja:
- Cara 1: Ganti dengan Class biasa
class ButtonConfig {
final String label;
final Icon icon;
final void Function()? onPressed;
ButtonConfig({required this.label, required this.icon, this.onPressed});
// Tambah metode kustom
bool get hasClickEvent => onPressed != null;
}
Code language: PHP (php)
- Cara 2: Bungkus Record lama pakai Extension Type
extension type ButtonConfig._(({String label, Icon icon, void Function()? onPressed}) _) {
String get label => _.label;
Icon get icon => _.icon;
void Function()? get onPressed => _.onPressed;
ButtonConfig({required String label, required Icon icon, void Function()? onPressed})
: this._((label: label, icon: icon, onPressed: onPressed));
bool get hasClickEvent => _.onPressed != null;
}
Code language: PHP (php)
Dua cara migrasi di atas tidak mengubah kode bisnis yang looping render tombol di halaman sama sekali.
X. Ringkasan
- Syarat versi: Dart 3.0 ke atas;
- Tiga properti inti: anonim, tidak dapat diubah, agregat; panjang tetap, penyimpanan heterogen, tipe kuat;
- Dua jenis field: field posisi
$1/$2, field bernama.nama; - Aturan penentuan tipe: tipe ditentukan bentuk struktur, nama field bernama masuk bagian bentuk; alias field posisi hanya komentar;
- Perbandingan sama: bentuk sama + semua nilai field cocok → true;
- Kelebihan utama: nilai balik banyak fungsi, wadah data ringan, keamanan tipe penuh;
- Cara perluasan: typedef sederhanakan alias tipe, nanti bisa ganti mulus ke class / extension type.