Beberapa operasi terasa lebih natural bila ditulis sebagai a op b daripada a.op(b). Pemanggilan 2 kali 3 lebih mudah dibaca daripada 2.kali(3) pada konteks matematika. Kotlin menyediakan infix functions untuk kebutuhan ini. Pada chapter ini kita akan melihat cara mendeklarasikan infix function dan aturan pemanggilannya.

Deklarasi infix Function #

Keyword infix diletakkan sebelum fun. Infix function harus menjadi member function atau extension function, dan harus menerima tepat satu parameter. Pemanggilan dilakukan dengan bentuk penerima namaFunction argumen.

kotlin
infix fun Int.kali(x: Int): Int = this * x

infix fun String.berulang(n: Int): String = this.repeat(n)

infix fun String.sambung(other: String): String = "$this-$other"

fun main() {
    val hasil = 2 kali 3
    println("2 kali 3 = $hasil")

    val garis = "-" berulang 10
    println("Garis: $garis")

    val namaGabung = "kotlin" sambung "dasar"
    println("Nama gabung: $namaGabung")

    val berurutan = (5 kali 4) kali 2
    println("5 kali 4 kali 2 = $berurutan")
}

Output yang Dihasilkan:

text
2 kali 3 = 6
Garis: ----------
Nama gabung: kotlin-dasar
5 kali 4 kali 2 = 40

Mari kita bedah baris per baris:

  1. infix fun Int.kali(x: Int): Int = this * x: extension function pada Int dengan satu parameter x. Kata kunci infix mengizinkan pemanggilan dengan bentuk 2 kali 3.
  2. infix fun String.berulang(n: Int): extension function pada String dengan parameter Int. Pemanggilan "-", 10 ditulis "-" berulang 10.
  3. 2 kali 3: bentuk infix setara dengan 2.kali(3). Kompilator menerjemahkan keduanya ke pemanggilan yang sama.
  4. (5 kali 4) kali 2: pemanggilan infix berantai wajib diberi tanda kurung untuk menentukan urutan operasi. Tanpa tanda kurung, 5 kali 4 kali 2 akan dianggap ambigu dan ditolak kompilator.

Syarat Deklarasi #

Tiga syarat wajib agar sebuah function dapat ditandai infix:

  • menjadi member function dari class atau extension function pada tipe tertentu
  • menerima tepat satu parameter (boleh memiliki default value, tetapi jumlahnya satu)
  • parameter tidak boleh vararg dan tidak boleh menerima jumlah argumen variabel

Syarat tersebut menjaga sintaks infix tetap sederhana: bentuk a op b memerlukan dua operand dan satu operator.

kotlin Contoh: member function infix di dalam class
class Wadah(val nilai: Int) {
    infix fun gabung(lain: Wadah): Wadah = Wadah(this.nilai + lain.nilai)
}

fun main() {
    val a = Wadah(10)
    val b = Wadah(20)
    val c = a gabung b
    println(c.nilai)
}

Member function gabung di dalam class Wadah juga dapat ditandai infix. Pemanggilan a gabung b setara dengan a.gabung(b).

Aturan Precedence dan Associativity #

Infix function memiliki precedence yang sama dengan operator perkalian dan pembagian. Bila dua infix function berdekatan, kompilator wajib diberi tanda kurung untuk menentukan urutan operasi. Tanpa tanda kurung, kompilator melaporkan galat ambigu.

kotlin Contoh: precedence infix
infix fun Int.tambah(n: Int): Int = this + n
infix fun Int.kurang(n: Int): Int = this - n

fun main() {
    val a = (10 tambah 5) kurang 3   // valid: hasil 12
    val b = 10 tambah (5 kurang 3)   // valid: hasil 12
    // val c = 10 tambah 5 kurang 3  // GALAT: ambigu
}

Pemanggilan yang ditandai komentar di atas menimbulkan galat karena kompilator tidak tahu apakah 5 menjadi argumen tambah atau kurang. Tanda kurung eksplisit menyelesaikan ambiguitas tersebut.

Kapan Menggunakan infix #

Infix function paling cocok untuk operasi yang secara semantik mirip dengan operator — misalnya kali, ditambah, kepada, hingga. Bila sebuah function melakukan tugas kompleks dengan banyak efek samping, bentuk pemanggilan reguler dengan titik dan kurung sering kali lebih jelas.

kotlin Contoh: kasus tepat dan kurang tepat
infix fun Int.ke(batas: Int): IntRange = this..batas  // Tepat: mirip operator rentang

infix fun String.kirimKe(email: String): Unit {       // Kurang tepat: efek samping IO
    println("Mengirim '$this' ke $email")
}

ke terasa natural sebagai operator, sedangkan kirimKe yang mengakibatkan efek samping IO lebih baik dipanggil dalam bentuk reguler agar pembaca menyadari adanya aksi non-trivial.

Referensi Lanjutan #

Ringkasan #

Infix function memungkinkan pemanggilan dengan bentuk a op b yang terbaca seperti kalimat. Function demikian harus member atau extension function dengan tepat satu parameter. Tanda kurung wajib dipakai saat memanggil infix secara berantai. Pada chapter operator Functions berikutnya, kita akan melihat bagaimana Kotlin memungkinkan kita mendefinisikan ulang operator seperti +, *, dan in menggunakan keyword operator.