Pemrograman Dart
Fungsi: Parameter Posisi, Named Parameter, dan Nilai Kembalian
Pelajari cara mengelompokkan logika program ke dalam fungsi di Dart 3, mulai dari nilai kembalian, parameter posisi wajib maupun opsional, hingga named parameter.

Saat program yang kita tulis mulai berkembang, menumpuk seluruh logika di dalam main() akan membuat kode sulit dibaca, rawan salah ketika diubah, dan penuh pengulangan (duplikasi). Bayangkan jika rumus perhitungan diskon dan pajak yang sama harus ditulis ulang di lima tempat berbeda—ketika aturan pajak berubah, kita wajib mencari dan mengedit kelima baris tersebut satu per satu. Fungsi (function) menyelesaikan masalah ini dengan membungkus serangkaian instruksi ke dalam satu blok bernama yang dapat dipanggil berkali-kali dengan masukan (parameter) yang berbeda dan menghasilkan nilai keluaran (return value) yang terprediksi.
Yang akan dipelajari
- Mendeklarasikan fungsi dengan tipe nilai kembalian (return type) yang eksplisit maupun
void. - Menulis fungsi satu baris secara ringkas menggunakan sintaks panah (arrow syntax
=>). - Membedakan parameter posisi wajib (required positional) dan opsional (
[...]). - Menggunakan named parameter (
{required ...}dan nilai default) untuk membuat pemanggilan fungsi jauh lebih terbaca.
Anatomi fungsi di Dart
Sebuah fungsi di Dart terdiri dari empat bagian utama: tipe kembalian, nama fungsi (mengikuti konvensi camelCase), daftar parameter di dalam tanda kurung, dan badan fungsi (body).
| Komponen | Contoh | Fungsi dan aturan di Dart 3 |
|---|---|---|
| Tipe kembalian (return type) | int, String, bool, void |
Menentukan tipe data yang dikembalikan oleh return. Gunakan void jika fungsi hanya menjalankan aksi tanpa mengembalikan nilai. |
| Nama fungsi | hitungTotalHarga |
Ditulis dengan gaya lowerCamelCase dan sebaiknya diawali kata kerja yang menjelaskan aksinya. |
| Parameter | (int harga, int jumlah) |
Variabel lokal yang menerima nilai (argumen) saat fungsi dipanggil. |
| Badan fungsi | { return ...; } atau => ...; |
Blok kode yang dieksekusi. Jika hanya berisi satu ekspresi, dapat disingkat dengan =>. |
Mari kita lihat cara mendeklarasikan fungsi biasa, fungsi void, serta fungsi satu baris dengan sintaks panah (=>) di DartPad:
// Fungsi dengan nilai kembalian bertipe double
double hitungLuasPersegiPanjang(double panjang, double lebar) {
return panjang * lebar;
}
// Fungsi satu baris (arrow function) — otomatis mengembalikan hasil ekspresi di kanan =>
int kuadrat(int angka) => angka * angka;
// Fungsi void — tidak mengembalikan nilai, hanya mencetak teks ke layar
void cetakGarisPemisah() {
print('----------------------------------------');
}
void main() {
cetakGarisPemisah();
double luas = hitungLuasPersegiPanjang(12.5, 4.0);
print('Luas persegi panjang: $luas');
print('Kuadrat dari 9 adalah ${kuadrat(9)}');
cetakGarisPemisah();
}
Keluaran program:
----------------------------------------
Luas persegi panjang: 50.0
Kuadrat dari 9 adalah 81
----------------------------------------
Perhatikan bahwa sintaks => ekspresi; hanyalah bentuk singkat dari { return ekspresi; }. Jangan menulis kata kunci return lagi setelah tanda =>.
Parameter posisi: wajib vs opsional ([...])
Secara bawaan, parameter yang ditulis langsung di dalam tanda kurung (a, b) adalah parameter posisi wajib (required positional parameters). Saat memanggil fungsi tersebut, jumlah dan urutan argumen yang dikirim harus persis sama dengan urutan deklarasinya.
Namun, terkadang ada parameter tambahan yang tidak selalu perlu diisi oleh pemanggil fungsi. Di Dart, kita dapat membungkus parameter posisi opsional menggunakan tanda kurung siku [...].
Aturan null safety pada parameter opsional
Karena parameter opsional boleh tidak diisi saat fungsi dipanggil, Sound Null Safety di Dart 3 mengharuskan kita memilih salah satu dari dua pendekatan berikut:
- Memberikan nilai bawaan (default value), misalnya
[String gelar = ''], sehingga variabel tidak pernah bernilainull. - Menjadikan tipenya nullable dengan tanda tanya, misalnya
[String? gelar], lalu menangani kemungkinannulldi dalam fungsi.
// Parameter 'gelarBelakang' bersifat opsional dan bertipe nullable (String?)
// Parameter 'sapaan' bersifat opsional dengan nilai bawaan 'Halo'
String formatNamaLengkap(
String namaDepan,
String namaBelakang, [
String? gelarBelakang,
String sapaan = 'Halo',
]) {
String namaUtama = '$namaDepan $namaBelakang';
if (gelarBelakang != null && gelarBelakang.isNotEmpty) {
return '$sapaan, $namaUtama, $gelarBelakang';
}
return '$sapaan, $namaUtama';
}
void main() {
// 1. Hanya mengirim parameter wajib
print(formatNamaLengkap('Budi', 'Santoso'));
// 2. Mengirim parameter wajib + parameter opsional pertama
print(formatNamaLengkap('Siti', 'Aminah', 'S.Kom.'));
// 3. Mengirim seluruh parameter sesuai urutan posisi
print(formatNamaLengkap('Andi', 'Wijaya', 'M.T.', 'Selamat pagi'));
}
Keluaran program:
Halo, Budi Santoso
Halo, Siti Aminah, S.Kom.
Selamat pagi, Andi Wijaya, M.T.
Kelemahan parameter posisi opsional terlihat pada pemanggilan ketiga: jika kita hanya ingin mengubah sapaan tanpa mengisi gelarBelakang, kita tetap terpaksa mengirim null pada posisi ketiga: formatNamaLengkap('Andi', 'Wijaya', null, 'Selamat pagi'). Untuk mengatasi masalah keterbacaan ini, Dart menyediakan named parameters.
Named parameter ({...} dan required)
Named parameter dibungkus dengan tanda kurung kurawal {...} pada deklarasi fungsi. Saat memanggil fungsi, kita menyebutkan nama parameternya secara eksplisit menggunakan format namaParameter: nilai. Keuntungannya sangat besar:
- Urutan pengiriman argumen bebas dan tidak harus mengikuti urutan deklarasi.
- Kode di lokasi pemanggilan menjadi sangat jelas (self-documenting), terutama jika fungsi menerima banyak parameter bertipe sama (
boolataudouble).
Secara bawaan, named parameter bersifat opsional. Jika sebuah named parameter wajib diisi oleh pemanggil fungsi, tambahkan kata kunci required di depan tipenya.
| Jenis Parameter | Sintaks Deklarasi | Contoh Pemanggilan | Sifat Wajib / Opsional |
|---|---|---|---|
| Positional wajib | (String nama, int umur) |
f('Budi', 20) |
Wajib, urutan harus tepat |
| Positional opsional | (String nama, [int umur = 18]) |
f('Budi') atau f('Budi', 20) |
Opsional, bergantung urutan |
| Named dengan default | ({int diskon = 0}) |
f() atau f(diskon: 10) |
Opsional, urutan bebas |
| Named nullable | ({String? catatan}) |
f() atau f(catatan: 'Fragile') |
Opsional, otomatis null jika dilewati |
| Named wajib | ({required int harga}) |
f(harga: 50000) |
Wajib, urutan bebas |
Kita juga dapat menggabungkan parameter posisi wajib di bagian depan, diikuti oleh blok named parameter {...} di bagian akhir:
double hitungTagihanAkhir(
String namaPelanggan, {
required double totalBelanja,
double persenDiskon = 0.0,
double biayaPengiriman = 15000,
bool memberPrioritas = false,
}) {
double potongan = totalBelanja * (persenDiskon / 100);
double ongkir = memberPrioritas ? 0 : biayaPengiriman;
double totalAkhir = (totalBelanja - potongan) + ongkir;
print('Pelanggan : $namaPelanggan');
print('Total Belanja : Rp${totalBelanja.toStringAsFixed(0)}');
print('Potongan Diskon : Rp${potongan.toStringAsFixed(0)}');
print('Ongkos Kirim : Rp${ongkir.toStringAsFixed(0)}');
print('Total Tagihan : Rp${totalAkhir.toStringAsFixed(0)}');
print('-----------------------------------');
return totalAkhir;
}
void main() {
// Memanggil dengan hanya mengisi parameter wajib
hitungTagihanAkhir(
'Rina Kartika',
totalBelanja: 120000,
);
// Urutan named parameter bebas dan sangat mudah dibaca
hitungTagihanAkhir(
'Dimas Pratama',
memberPrioritas: true,
persenDiskon: 15,
totalBelanja: 200000,
);
}
Keluaran program:
Pelanggan : Rina Kartika
Total Belanja : Rp120000
Potongan Diskon : Rp0
Ongkos Kirim : Rp15000
Total Tagihan : Rp135000
-----------------------------------
Pelanggan : Dimas Pratama
Total Belanja : Rp200000
Potongan Diskon : Rp30000
Ongkos Kirim : Rp0
Total Tagihan : Rp170000
-----------------------------------
Kaitannya dengan Flutter / Dunia Nyata: Hampir seluruh komponen antarmuka (widget) di Flutter dirancang menggunakan kombinasi satu parameter posisi utama dan puluhan named parameter. Contohnya saat Anda menulis
Text('Selamat Datang', textAlign: TextAlign.center, maxLines: 2)atauElevatedButton(onPressed: simpanData, child: Text('Simpan')). Memahamirequireddan named parameter sejak sekarang akan membuat Anda langsung akrab membaca kode Flutter.
Coba sendiri
Buka DartPad, salin kode hitungTagihanAkhir di atas, lalu lakukan eksperimen berikut:
- Tambahkan satu named parameter baru bernama
String? kodeVoucherpada fungsihitungTagihanAkhir. - Di dalam badan fungsi, tambahkan pengecekan: jika
kodeVoucher == 'HEMAT20', kurangi lagitotalAkhirsebesar20000. - Panggil fungsi tersebut di
main()dengan menyertakankodeVoucher: 'HEMAT20'dan amati perubahan total tagihannya. - Coba hapus argumen
totalBelanja: ...pada salah satu pemanggilan dimain()dan perhatikan pesan error kompilasi yang diberikan DartPad karena melanggar kontrakrequired.
Kesalahan yang sering terjadi
| Kesalahan Umum | Penyebab | Solusi yang Benar |
|---|---|---|
| Error: The parameter 'x' can't have a value of 'null' because of its type | Mendeklarasikan parameter opsional [int x] atau {int x} dengan tipe non-nullable tanpa nilai default maupun required. |
Tambahkan nilai bawaan ({int x = 0}), jadikan nullable ({int? x}), atau tambahkan required ({required int x}). |
Menulis { return a + b; } setelah tanda => (int tambah(int a, int b) => return a + b;) |
Mencampur sintaks blok { return ...; } dengan sintaks ekspresi satu baris =>. |
Cukup tulis ekspresinya saja setelah panah: int tambah(int a, int b) => a + b;. |
Menggabungkan [...] dan {...} dalam satu fungsi yang sama |
Dart tidak mengizinkan parameter posisi opsional [...] dan named parameter {...} dipakai bersamaan dalam satu deklarasi fungsi. |
Pilih salah satu. Praktik terbaik Effective Dart menyarankan penggunaan named parameter {...} untuk kejelasan kode. |
Tidak menuliskan tipe kembalian fungsi (hitung(int a) { ... }) |
Jika tipe kembalian dihilangkan, Dart menganggap tipe kembaliannya adalah dynamic, sehingga kehilangan pemeriksaan tipe saat kompilasi. |
Selalu tulis tipe kembalian secara eksplisit (int, String, void, dll.) di depan nama fungsi. |
Latihan
Kerjakan tiga soal bertingkat berikut di DartPad untuk menguji pemahaman Anda:
- Konversi Suhu (Arrow Function & Positional Parameter): Buatlah dua fungsi satu baris (
=>) bernamacelciusKeFahrenheit(double c)dengan rumus(c * 9 / 5) + 32dancelciusKeKelvin(double c)dengan rumusc + 273.15. Panggil keduanya dimain()untuk suhu25.0derajat Celcius. - Pembuat URL Pencarian (Positional & Named Parameter): Buat fungsi
buatUrlPencarian(String kataKunci, {int halaman = 1, int batas = 10, String? kategori}). Fungsi ini mengembalikanStringberupa URL. Jikakategoritidaknull, kembalikan'https://toko.id/cari?q=$kataKunci&page=$halaman&limit=$batas&cat=$kategori'. Jikakategoribernilainull, bagian&cat=...tidak perlu disertakan. - Validator Pendaftaran Kursus (
requiredNamed Parameter & Record): Buat fungsivalidasiPendaftaran({required String nama, required int umur, String? email, bool setujuSyarat = false})yang mengembalikan Record(bool valid, String pesan). Pendaftaran dinyatakan valid hanya jikanamatidak kosong,umur >= 15, dansetujuSyaratbernilaitrue. Jika lolos, kembalikan(true, 'Pendaftaran $nama berhasil')(sertakan info email jika diisi). Jika gagal, kembalikan(false, ...)beserta alasan kegagalannya.
Kunci jawaban dan pembahasan
Latihan 1
double celciusKeFahrenheit(double c) => (c * 9 / 5) + 32;
double celciusKeKelvin(double c) => c + 273.15;
void main() {
double suhuC = 25.0;
print('$suhuC °C = ${celciusKeFahrenheit(suhuC)} °F');
print('$suhuC °C = ${celciusKeKelvin(suhuC)} K');
}
Pembahasan: Karena kedua rumus konversi suhu hanya terdiri dari satu ekspresi matematika tunggal, penggunaan arrow syntax (=>) membuat deklarasi fungsi jauh lebih ringkas tanpa mengorbankan kejelasan tipe parameter maupun tipe kembaliannya (double).
Latihan 2
String buatUrlPencarian(
String kataKunci, {
int halaman = 1,
int batas = 10,
String? kategori,
}) {
String urlDasar =
'https://toko.id/cari?q=$kataKunci&page=$halaman&limit=$batas';
if (kategori != null && kategori.isNotEmpty) {
return '$urlDasar&cat=$kategori';
}
return urlDasar;
}
void main() {
print(buatUrlPencarian('laptop'));
print(buatUrlPencarian('sepatu', halaman: 2, kategori: 'olahraga'));
}
Pembahasan: Parameter kataKunci diletakkan sebagai parameter posisi wajib karena pencarian selalu membutuhkan kata kunci utama. Sementara itu, halaman dan batas diberi nilai default karena pengguna umumnya mulai dari halaman pertama, sedangkan kategori dibuat nullable (String?) karena filter kategori bersifat opsional.
Latihan 3
(bool, String) validasiPendaftaran({
required String nama,
required int umur,
String? email,
bool setujuSyarat = false,
}) {
if (nama.trim().isEmpty) {
return (false, 'Gagal: Nama peserta tidak boleh kosong.');
}
if (umur < 15) {
return (false, 'Gagal: Umur minimal pendaftaran adalah 15 tahun.');
}
if (!setujuSyarat) {
return (false, 'Gagal: Anda harus menyetujui syarat dan ketentuan.');
}
String infoEmail = (email != null && email.isNotEmpty)
? ' (konfirmasi dikirim ke $email)'
: '';
return (true, 'Pendaftaran $nama berhasil$infoEmail.');
}
void main() {
var hasil1 = validasiPendaftaran(
nama: 'Nadia',
umur: 19,
email: 'nadia@example.com',
setujuSyarat: true,
);
print('Status: ${hasil1.$1} | Pesan: ${hasil1.$2}');
var hasil2 = validasiPendaftaran(
nama: 'Riko',
umur: 17,
);
print('Status: ${hasil2.$1} | Pesan: ${hasil2.$2}');
}
Pembahasan: Kita memanfaatkan fitur Record (bool, String) dari Dart 3 yang telah dipelajari pada materi sebelumnya sebagai tipe kembalian fungsi. Dengan teknik early return (langsung mengembalikan (false, ...) begitu ada syarat yang tidak terpenuhi), kode fungsi menjadi rata, bersih, dan terhindar dari if-else bersarang yang dalam.
Discussion (0)
We store your optional name, your comment, and technical hashes (not your raw IP address) to prevent spam. A functional cookie lets you edit or delete your own comments from this browser. To request deletion, use the contact page.
No comments yet. Start the discussion.