0% menganggap dokumen ini bermanfaat (0 suara)
14 tayangan212 halaman

Pengenalan Kotlin

Diunggah oleh

Prana As
Hak Cipta
© © All Rights Reserved
Kami menangani hak cipta konten dengan serius. Jika Anda merasa konten ini milik Anda, ajukan klaim di sini.
Format Tersedia
Unduh sebagai DOCX, PDF, TXT atau baca online di Scribd
0% menganggap dokumen ini bermanfaat (0 suara)
14 tayangan212 halaman

Pengenalan Kotlin

Diunggah oleh

Prana As
Hak Cipta
© © All Rights Reserved
Kami menangani hak cipta konten dengan serius. Jika Anda merasa konten ini milik Anda, ajukan klaim di sini.
Format Tersedia
Unduh sebagai DOCX, PDF, TXT atau baca online di Scribd
Anda di halaman 1/ 212

Pengenalan Kotlin

Pada tahun 2010 lalu JetBrains memulai sebuah proyek open-sources


baru. Proyek ini merupakan sebuah bahasa pemrograman statically
typed yang
menargetkan JVM, Android, JavaScript dan Native [1]. Kotlin -nama
sebuah pulau di Rusia- menjadi inspirasi oleh tim pengembang untuk
ditetapkan sebagai nama bahasa pemrograman tersebut. Mungkin
karena pulau tersebut terletak tidak jauh dari markas tim programer
JetBrains, yaitu Saint Petersburg, Rusia. Bahasa Kotlin pertama kali
dirilis pada bulan Februari 2016 dengan versi 1.0. Saat ini sudah
mencapai versi 1.5.21 per rilis 14 Juli 2021.

Di balik kemajuan pesatnya Kotlin, terdapat pengembang -


pengembang hebat dan kreatif dari JetBrains. Kotlin dikembangkan
oleh lebih dari 50 developer pimpinan Andrey Breslav. Mereka semua
terinspirasi dari bahasa pemrograman yang sudah ada seperti Java,
Scala, JavaScript, C# dan juga Groovy. Apa yang membedakan? Salah
satunya, JetBrains memastikan bahwa Kotlin sangat mudah dipelajari.

Karena tergolong proyek open-sources, Kotlin dapat bebas kita


gunakan secara gratis. Kotlin dikembangkan di bawah lisensi Apache
2.0 dan kode sumbernya bisa Anda akses di laman GitHub-nya. Kita
pun bisa berkontribusi dengan mengirimkan pull request ke repository-
nya.
Kotlin dapat digunakan untuk berbagai macam pengembangan
aplikasi, baik itu server atau backend, website, maupun mobile
Android. Bahkan saat ini tengah dikembangkan Kotlin/Native. Apa
uniknya? Kotlin/Native memungkinkan developer untuk
menggunakannya sebagai bahasa pemrograman dalam
pengembangan aplikasi di platform lain seperti embedded system,
desktop, macOS, dan iOS. Bahkan tak menutup kemungkinan Kotlin
juga bisa digunakan untuk data science dan machine learning. Menarik,
bukan?

Dukungan tools untuk Kotlin , sangat kuat. Kita bisa dengan mudah
menggunakan Kotlin pada IDE seperti IntelliJ IDEA, Android
Studio, Eclipse, dan NetBeans. Anda pun bisa menggunakan perintah
terminal untuk mengkompilasi dan menjalankan Kotlin. Begitu pula
untuk build tools. Pada JVM kita bisa
menggunakan Gradle, Maven, Ant, atau Kobalt. Tersedia juga
beberapa build tools yang menargetkan JavaScript.

Sebagaimana dijelaskan, kita bisa menargetkan Kotlin ke beberapa


target. Kotlin akan menghasilkan bytecode yang berbeda sesuai dengan
targetnya. Ketika menargetkan JVM, Kotlin akan
menghasilkan bytecode yang kompatibel dengan Java. Kemudian ketika
menargetkan JavaScript, Kotlin akan melakukan transpile ke ES5.1 dan
menghasilkan kode yang kompatibel dengan sistem sub-modul
termasuk AMD dan CommonJS. Sedangkan untuk native, Kotlin akan
menghasilkan kode yang spesifik dengan platformnya melalui LLVM.

Pada sub-modul ini kita akan mencoba mengenal Kotlin secara lebih
mendalam. Harapannya, sebelum mempelajari komponen-komponen
pada Kotlin secara spesifik, kita semua bisa memahami untuk apa saja
Kotlin bisa digunakan, apa saja kelebihan dan kekurangannya,
karakteristiknya, dan juga seperti apa ekosistem Kotlin di dunia
pengembangan aplikasi.

Kotlin Sebagai Bahasa Multiparadigm


Apa keunikan Kotlin? Salah satunya, Kotlin merupakan sebuah bahasa
pemrograman yang bisa ditargetkan untuk berbagai macam platform
(Multiplatform) dan juga memiliki beberapa paradigma
(Multiparadigm). Oleh karena itu, kita perlu tahu apa maksud dari
Multiplatform dan Multiparadigm tersebut. Mari kita bahas satu per
satu.

Multiparadigm

Mungkin sebagian dari kita masih asing dengan istilah multiparadigm


di dunia programing. Programming paradigm adalah sebuah cara
untuk mengklasifikasikan bahasa pemrograman berdasarkan fitur
yang dimilikinya. Paradigma disini berkaitan dengan bagaimana kode
dalam sebuah bahasa pemrograman diatur, seperti mengelompokkan
kode atau memodifikasinya. Lebih tepatnya, seperti apa struktur kode
bisa diterapkan pada bahasa pemrograman tersebut.

Terdapat beberapa paradigma yang umum dimiliki oleh sebuah


bahasa pemrograman. Ketika kita ingin mengklasifikasikan bahasa
pemrograman berdasarkan cara penulisan sintaksnya, object-oriented
programming (OOP) dan functional programming (FP) merupakan 2
(dua) paradigma yang terkenal di kalangan developer. Dari sisi
konstruksi, Kotlin sendiri mencakup keduanya. Anda bisa
menggunakan gaya OOP maupun FP, bahkan mencampurnya saat
menuliskan sintaks Kotlin. Dengan dukungan tinggi untuk fitur-fitur
seperti higher-order function, function types, dan lambda, Kotlin
adalah pilihan yang tepat untuk Anda mengeksplorasi functional
programming. Hampir semua General Purpose Language sekarang
sudah mendukung multiparadigm. Untuk lebih jelasnya, mari kita
bahas satu per satu kedua paradigma tersebut.

Object-oriented Programming

Suatu bahasa pemrograman bisa diklasifikasikan ke dalam OOP jika


data dan metode yang digunakan untuk memanipulasinya disimpan
sebagai satu unit yang bisa disebut dengan objek. OOP memiliki fitur
enkapsulasi yang sempurna. Lebih lanjut, satu-satunya cara yang bisa
digunakan agar objek atau pengguna lain dapat mengakses suatu data
adalah dengan metode objek. Dengan demikian, cara kerja suatu objek
dapat diubah tanpa mempengaruhi kode lain yang menggunakan
objek tersebut.

Kotlin memberikan dukungan yang luas untuk mengembangkan


program berorientasi objek. Di dalam OOP kita akan mengenal
beberapa konsep seperti object, classes, properties, constructor, dll.
Dengan OOP kita bisa memecahkan persoalan yang kompleks menjadi
set yang lebih kecil dengan membuat objek. Objek tersebut memiliki 2
(dua) karakteristik utama, yaitu state (keadaan)
dan behaviour (perilaku).

Kita akan membahas mengenai komponen-komponen OOP pada


Kotlin secara lebih mendalam pada sub-modul tersendiri. Sebagai
pembuka, mari kita perhatikan contoh berikut.

1. Sepeda motor adalah sebuah objek. Sepeda motor memiliki 2


(dua) roda, tahun produksi, berat, dan kecepatan maksimum,
yang mana bisa kita sebut sebagai states. Selain itu, sepeda
motor bisa melaju, direm, dan juga berganti gigi. Nah, ketiga hal
tersebut bisa kita sebut sebagai behaviour.
2. Contoh lainnya adalah seekor kuda. Kuda adalah sebuah objek.
Kuda memiliki nama, warna, dan juga jenis yang mana
merupakan states dari Kuda. Kuda bisa berlari, makan, dan lain
sebagainya. Inilah yang kita sebut sebagai behaviour.
Sebuah objek seperti sepeda motor juga bisa memiliki objek-objek
kecil di dalamnya, misalnya roda, rem, body, mesin dll. Semuanya bisa
saling berhubungan dan berinteraksi. Selain itu, OOP juga berdasar
pada konsep Message Passing, yakni sebuah tipe komunikasi antara
proses dan objek. Itulah gambaran sederhana konsep OOP yang akan
kita pelajari.

Functional Programming

Ada begitu banyak persepsi mengenai functional programming. Setiap


persepsi tergantung siapa yang mengartikannya. Seorang F-sharp
programer akan mengartikan FP sebagai apa yang ada pada F-sharp.
Demikian halnya Swift programer akan mengartikan FP sebagai apa
yang ada pada Swift. Namun kita bisa menyimpulkan bahwa semua
bahasa pemrograman yang mendukung first-class citizen termasuk ke
dalam FP. First-class citizen sendiri merupakan sebuah entitas yang
mendukung semua operasi yang umumnya tersedia untuk entitas lain.
Sebagai contoh, sebuah fungsi yang bisa dikirimkan sebagai
parameter.

Functional programming merupakan paradigma yang sedang hype di


kalangan developer saat ini. Paradigma ini memperlakukan komputasi
sebagai evaluasi fungsi matematika dan menghindari perubahan
keadaan atau state dan data yang bisa berubah. Dalam FP,
pemrograman dilakukan dengan expression atau declaration. Sehingga
sebuah fungsi menghasilkan nilai yang hanya bergantung pada
argumen yang diteruskan ke fungsi tersebut. Menghilangkan efek
seperti perubahan state yang tidak tergantung pada fungsi input,
dapat membuatnya lebih mudah untuk memahami dan
memprediksi behaviour sebuah program. Inilah tujuan utama
dari functional programming.
Masih banyak developer yang langsung membayangkan OOP ketika
mendengar kata “Kotlin”. Padahal seperti yang telah disebutkan
sebelumnya, Kotlin merupakan multiparadigm language. Kotlin memiliki
beberapa fitur yang memiliki gaya functional programming, walaupun
tidak sepenuhnya functional programming. Mengapa demikian?
Sesungguhnya Kotlin adalah sebuah bahasa pemrograman
berorientasi objek yang memiliki struktur fungsional. Ini artinya Kotlin
juga merupakan sebuah functional programming language.

Functional programming juga bertujuan untuk mempermudah kita


memahami sebuah kode. Ide dibalik FP adalah menambahkan dan
mengurangi hal tertentu untuk membuat kode kita sedikit lebih mudah
dipahami. Kotlin memiliki banyak fitur menarik yang membuatnya bisa
disebut dengan functional programming seperti higher-order function,
function types, extension functions, lambda, dll. Kita akan membahas
kembali mengenai functional programming pada Kotlin dan fitur-fitur
tersebut pada sub-modul tersendiri. Siap lanjut?

Multiplatform

Multiplatform berarti mendukung lebih dari 1 (satu) platform. Ketika


kita membahas tentang aplikasi multiplatform, bisa dikatakan aplikasi
tersebut tersedia pada lebih dari 1 (satu) platform atau bahkan
bermacam-macam platform. Platform yang dimaksud misalnya
Android, iOS, Web, Desktop, dsb. Kotlin merupakan
sebuah multiplatform programming language. Kotlin bisa digunakan
untuk mengembangkan aplikasi dalam berbagai platform. Namun,
sebenarnya tujuan dari multiplatform pada Kotlin sendiri tidak sekedar
itu. Kotlin memiliki tujuan yang lebih penting, yaitu berbagi kode antar
platform. Dengan dukungan
untuk JVM, Android, JavaScript, iOS, Linux, Windows, macOS dan
bahkan embedded system seperti STM32, Kotlin mampu mengatasi
komponen apa pun yang terdapat pada aplikasi modern.

Banyak developer kira multiplatform artinya membuat sebuah proyek


dan langsung bisa dijalankan di atas semua platform. Tidak salah,
tetapi tahukah Anda jika model seperti itu memiliki beberapa
kekurangan? Sebuah aplikasi modern pasti akan membutuhkan akses
ke fitur-fitur tertentu pada platform yang menjalankannya. Misalnya,
mengakses fitur pada ponsel seperti gyroscope, motion, GPS, dan lain
sebagainya. Melakukan hal tersebut menggunakan framework
multiplatform (cross platform) tentunya tak semudah menggunakan
bahasa pemrograman khusus untuk platform tertentu (Native).
Misalnya, Android menggunakan Java atau Kotlin dan iOS
menggunakan Swift atau Objective-C. Belum lagi ketika membahas
masalah performa, native pasti jauh lebih unggul dari cross platform.

Kotlin menawarkan konsep multiplatform yang sedikit berbeda.


Dengan model code-sharing yang ada, memungkinkan Anda untuk
mengelompokkan beberapa kode sesuai fungsi masing-masing.
Sebagai contoh, membuat modul A yang berisi kumpulan kode yang
dapat diakses oleh semua platform, modul B yang berisi kode spesifik
untuk platform tertentu, dan modul C yang ditargetkan untuk platform
tertentu, tetapi juga memiliki ketergantungan ke modul lain.

Perhatikan diagram berikut.


Kurang lebih seperti itulah gambaran dari modul yang bisa kita buat
pada project Kotlin multiplatform. Modul tersebut dapat kita bagi
menjadi 3 (tiga) bagian berikut.

 Common Module
Modul ini berisi kode yang tidak spesifik ke platform apa pun.
Kita bisa menempatkan komponen-komponen yang bisa
digunakan oleh semua modul pada modul ini.
 Platform Module
Pada modul ini kita bisa menambahkan komponen tertentu yang
spesifik untuk satu platform. Biasanya modul ini merupakan
implementasi dari common module.
 Regular Module
Merupakan modul umum yang menargetkan platform tertentu.
Modul ini bisa dependen atau pun menjadi dependensi
dari platform module.
Kotlin pun telah menyiapkan beberapa library khusus untuk
mendukung proyek multiplatform, di antaranya
adalah HTTP, serialization, dan coroutines. Semua library tersebut bisa
kita terapkan pada common module dan kemudian diakses oleh
modul lainnya. Anda pun tetap bisa menggunakan Kotlin standard
library pada semua modul. Tentunya ini akan sangat membantu
memudahkan proses pengembangan aplikasi.

Pada akademi ini kita tidak akan mempraktikkan aplikasi Kotlin


Multiplatform secara langsung pada sebuah proyek. Melainkan, kita
balik ke fokus awal akademi ini yaitu "Memulai Pemrograman
dengan Kotlin". Jika Anda penasaran dengan implementasi Kotlin
Multiplatform, Anda bisa mempelajarinya pada tautan berikut.

 Building Multiplatform Projects with Gradle


 Multiplatform Project: iOS and Android
 Compose Multiplatform (New)

JetBrains juga memiliki beberapa contoh proyek yang bisa kita pelajari
untuk menerapkan Kotlin Multiplatform:

 KotlinConf App
 KotlinConf Spinner App

Dokumentasi resmi dari Kotlin Multiplatform bisa Anda lihat


pada tautan ini.

Sebagai informasi tambahan bahwa saat ini Kotlin Multiplatform sudah


stabil hingga tingkat produksi. Jadi, saat ini Anda bisa
menggunakannya dalam real project.

Silakan baca selengkapnya di Kotlin Multiplatform Is Stable and


Production-Ready.
Kotlin untuk Aplikasi Server-side
Terdapat berbagai macam aplikasi server-side, mulai dari aplikasi Web
yang menampilkan halaman HTML, Backend yang menghasilkan API
untuk aplikasi mobile, dan juga aplikasi yang lebih kompleks seperti
Microservice. Semua aplikasi tersebut bisa dikembangkan
menggunakan Kotlin. Selain memungkinkan kita untuk menulis kode
yang ringkas dan ekspresif, Kotlin juga mempertahankan
kompatibilitas dengan teknologi berbasis Java.

Dengan membangun aplikasi server-side menggunakan Kotlin, kita


akan mendapatkan beberapa manfaat, antara lain:

 Expressiveness
Fitur-fitur pada Kotlin seperti type-safe builder dan delegated
properties akan membantu membangun abstraksi yang kuat dan
mudah digunakan.
 Scalability
Dukungan Kotlin untuk coroutines akan membantu kita.
Khususnya dalam membangun aplikasi server-side dengan skala
yang besar, namun menggunakan perangkat yang sederhana.
 Interoperability
Kotlin sepenuhnya kompatibel dengan semua framework Java. Ini
memungkinkan Anda tetap menggunakan teknologi yang sudah
ada dan mulai menggunakan bahasa yang lebih modern.
 Migration
Kotlin mendukung proses migrasi secara bertahap, dari Java ke
Kotlin. Anda dapat mulai menulis kode baru dengan Kotlin tanpa
memodifikasi kode Java yang sudah ada.
 Tooling
Selain dukungan IDE yang powerful, Kotlin menawarkan
beberapa plugin untuk framework spesifik seperti Spring.
Tersedia juga berbagai macam framework yang bisa Anda gunakan
untuk mempermudah pengembangan aplikasi server-side seperti:

1. Spring
Spring merupakan sebuah framework yang sangat terkenal di
Java. Spring bisa digunakan pada Kotlin untuk komunikasi ke API
dengan lebih ringkas. Tersedia juga Spring Initializr yang
memungkinkan kita untuk membuat proyek Spring baru dengan
Kotlin.
2. Vert.x
Merupakan sebuah framework untuk membuat reactive Web app
di JVM. Anda bisa melihat repository-nya
di https://github.com/vert-x3/vertx-lang-kotlin .
3. Ktor
Ktor adalah sebuah framework yang dikembangkan oleh JetBrains
untuk membuat aplikasi Web di Kotlin. Ktor memanfaatkan
coroutine untuk skalabilitas yang tinggi dan menawarkan API
yang mudah digunakan.
4. Kotlinx.html
Merupakan sebuah DSL yang dapat digunakan untuk membuat
HTML di aplikasi Web. Kotlinx.html dapat digunakan sebagai
alternatif untuk sistem templating tradisional seperti JSP dan
FreeMarker.
5. Exposed
Sebuah framework SQL yang menyediakan kumpulan DSL yang
mudah dibaca untuk menggambarkan struktur database SQL
dan melakukan kueri sepenuhnya dengan Kotlin.
Jelas terdapat berbagai kemudahan yang ditawarkan dan juga
dukungan framework yang kuat. Para developer tak perlu ragu lagi
dalam mencoba menerapkan Kotlin sebagai bahasa pemrograman
untuk mengembangkan aplikasi server-side. Anda pun bisa mulai
mencobanya dengan mengikuti beberapa dokumentasi berikut.

 Creating Web Applications with Http Servlets


 Creating a RESTful Web Service with Spring Boot

Kotlin untuk Aplikasi Android

Berbeda dengan aplikasi server-side, aplikasi mobile biasanya


membutuhkan proses pengembangan yang lebih cepat. Selain itu,
dengan begitu banyaknya tipe perangkat mobile, developer perlu
memastikan bahwa aplikasinya dapat berjalan dengan baik pada
semua perangkat. Dengan semua fitur yang Kotlin tawarkan,
terpenuhilah semua kebutuhan pada pengembangan aplikasi mobile.
Berikut ini adalah beberapa kelebihan mengembangkan aplikasi
Android dengan Kotlin.

 Compatibility
Kotlin sepenuhnya kompatibel dengan JDK 6. Ini memastikan
bahwa aplikasi yang dibangun dengan Kotlin dapat berjalan pada
perangkat Android yang lebih lama tanpa ada masalah. Android
Studio pun mendukung penuh pengembangan dengan bahasa
Kotlin.
 Performance
Dengan struktur bytecode yang sama dengan Java, aplikasi yang
dibangun dengan Kotlin dapat berjalan setara dengan aplikasi
yang dibangun dengan Java. Terdapat juga fitur seperti inline
function pada Kotlin yang membuat kode yang dituliskan
dengan lambda bisa berjalan lebih cepat dibandingkan kode
yang sama dan dituliskan dengan Java.
 Interoperability
Anda dapat menggunakan bahasa Kotlin bersamaan dengan
bahasa Java, tanpa harus memigrasikan semua kode lama Anda
ke Java. Sehingga, Anda dapat memanggil kode Java dari Kotlin
dan sebaliknya. Inilah alasan yang menyebabkan Kotlin menjadi
cepat diterima oleh developer.
 Compilation Time
Kotlin mendukung kompilasi inkremental yang efisien. Oleh
karena itu, proses build biasanya sama atau lebih cepat
dibandingkan dengan Java.
 Easy Learning
Kotlin sangat mudah untuk dikuasai, terlebih jika Anda
sebelumnya adalah Java Developer.
 Big Community
Kotlin memiliki banyak dukungan dan kontribusi dari komunitas,
yang mana pertumbuhannya sangat kencang di seluruh dunia.
Lebih dari 95% aplikasi terbaik di Play Store menggunakan Kotlin.
Perkembangan Kotlin pada Android pun bisa dibilang sangat cepat.
Bahkan pada acara Google I/O 2019 lalu, Google
mengumumkan Kotlin First!, yaitu menetapkan Kotlin sebagai bahasa
pemrograman nomor 1 (satu) untuk Android. Hampir semua update
pada Android saat ini sudah menggunakan Kotlin pada
dokumentasinya. Tim Android juga merilis Android Jetpack yang
merupakan sekumpulan library yang dapat digunakan untuk
memanfaatkan fitur bahasa Kotlin dengan lebih advanced. Dengan
kematangan Kotlin, banyak perusahaan siap menggunakan Kotlin
sebagai bahasa pemrograman untuk membangun aplikasi Android.

Semua dokumentasi juga disediakan dengan sangat jelas dan lengkap


pada https://developer.android.com/kotlin/ atau https://kotlinlang.org/
docs/android-overview.html.
Kotlin Sebagai Investasi
Beberapa pertanyaan yang sering muncul dari developer saat ingin
mulai belajar Kotlin adalah “Apakah worth it? Apa saja
keunggulannya? Mengapa kita harus mempelajarinya?.” Senada
dengan itu, kali ini kita akan membahas beberapa keuntungan dan
juga alasan mengapa kita harus mempelajari Kotlin.

Salah satu alasan JetBrains mengembangkan Kotlin adalah karena


mereka tak puas dengan Java dan ingin meningkatkan produktivitas
mereka. Seorang Java developer yang sudah mempelajari Kotlin, pasti
akan membenarkan pernyataan tersebut. Apa pasal? Karena memang
benar Java punya kekurangan pada beberapa aspek. Lalu seberapa
besar pengaruh Kotlin dalam produktivitas seorang developer?

Produktivitas memang menjadi salah satu faktor penting yang menjadi


alasan mengapa seorang developer harus mempelajari sebuah bahasa
pemrograman. Kotlin memiliki beberapa kelebihan yang dapat
meningkatkan produktivitas developer. Berikut beberapa kelebihan
tersebut:

1. Ringkas (Concise)
Selain mudah dipelajari, bahasa pemrograman baru yang satu ini
juga mudah untuk dituliskan. Sintaksisnya pun mudah dibaca
dan bisa dibilang lebih “manusiawi.” Mungkin karena penamaan
fungsi di dalamnya yang mirip dengan bahasa manusia sehari-
hari. Kotlin memungkinkan kita untuk mengurangi jumlah
penulisan kode boilerplate. Maka jangan heran jika kita sering
mendengar istilah “nicer Java”.
2. Dapat dioperasikan secara bersilangan (Interoperable)
Apakah Anda seorang Java developer yang ingin berpindah ke
Kotlin? Jangan khawatir, Kotlin dan Java sama-sama berjalan di
atas JVM. Alhasil, keduanya bisa dijalankan bersamaan dalam 1
(satu) proyek. Tentunya ini sangat menguntungkan. Kita tidak
perlu menuliskan ulang kode Java yang sudah ada. Anda cukup
menuliskan kode baru dengan Kotlin. Menariknya, selain bisa
dijalankan bersamaan, fungsi yang ada pada kedua bahasa
tersebut juga bisa saling diakses. Java bisa mengakses fungsi
yang ada pada Kotlin. Sebaliknya, Kotlin juga bisa mengakses
fungsi yang ada pada Java.
3. Dukungan tools yang memadai (Tool-friendly)
Membahas soal produktivitas, tentu tak jauh dari
dukungan tools yang diberikan. Saat ini banyak IDE yang
mendukung Kotlin. Tersedia juga https://play.kotlinlang.org/ yang
memungkinkan Anda mencoba Kotlin secara online. Kita pun
tetap bisa menggunakan command line atau terminal. Kita akan
mempelajari tentang IDE dan tools lainnya pada modul terpisah.
Dengan keunggulan-keunggulan Kotlin tersebut, bisa kita simpulkan
bahwa Kotlin merupakan bahasa pemrograman yang wajib kita
pelajari. Bagi seseorang yang baru mengenal pemrograman,
mempelajari Kotlin bisa menjadi investasi yang baik.
Dukungan multiplatform memungkinkan kita untuk merambah ke
berbagai platform. Lebih lanjut, konsep OOP dan FP bisa menjadi
modal utama seorang programmer untuk mempelajari bahasa
pemrograman lain di kemudian hari.

Kotlin Sebagai Bahasa Concise dan Pragmatic


Karakteristik Kotlin

Untuk kenal lebih dalam sebuah bahasa pemrograman, tentu kita


harus mengetahui karakteristik dari bahasa tersebut. Kotlin adalah
bahasa pemrograman yang ringkas, aman, pragmatis dan difokuskan
pada interoperabilitas dengan bahasa Java. Kotlin berjalan lancar
dengan semua library dan frameworks Java yang sudah ada. Tentunya
Kotlin juga memiliki karakteristik tersendiri yang membuatnya disukai
oleh banyak developer. Mari kita bahas bersama beberapa
karakteristik tersebut.

Modern and Concise

Kotlin dikenal dengan bahasa modern yang ringkas untuk dituliskan.


Kotlin mampu memangkas berbaris-baris kode menjadi hanya
beberapa baris saja. Seperti kita ketahui, programmer menghabiskan
banyak waktunya untuk membaca dan menuliskan kode. Ketika kita
sedang mengembangkan sebuah aplikasi, hal yang pertama kita
lakukan pastinya adalah membaca kode. Baik kode dari sebuah
dokumentasi atau pun kode yang sudah ada pada proyek yang sedang
dikerjakan. Membaca atau menuliskan kode yang ringkas dan mudah
dipahami tentunya menjadi sebuah keuntungan sendiri bagi seorang
programmer.

Semakin ringkas sebuah kode, maka semakin cepat pula untuk kita
pahami. Selain ringkas, faktor lain seperti penamaan fungsi juga akan
sangat berpengaruh. Kotlin memiliki fungsi-fungsi bawaan yang
namanya mudah diingat. Bahkan pilihan keyword yang terkesan sangat
sederhana. Mari kita perhatikan perbandingan antara Kotlin dan Java
berikut:

Java:

Kotlin:

“Hal apa yang pertama kali Anda lihat ketika melihat 2 (dua) kode
di atas?”.

“Kotlin tidak memerlukan semicolon atau tanda titik koma (;)”.

Ya benar, itu adalah salah satu ciri dari Kotlin. Sederhana, tapi tak
jarang programmer dibuat pusing karena lupa
menambahkan semicolon di akhir kode ketika ngoding dengan Java.
Kode di atas memiliki kegunaan yang sama namun dituliskan dengan
bahasa pemrograman yang berbeda. Terlihat dengan sangat jelas
bahwa kode yang dituliskan dengan Kotlin lebih ringkas dan lebih
mudah dipahami, bukan? Nah, itu belum seberapa. Pada akademi ini
Anda akan melihat banyak contoh kode yang menunjukan bahwa
Kotlin adalah bahasa yang sangat ringkas.

Kotlin juga dibekali dengan beberapa standard library seperti higher-


order function, extension function, dll yang membuat penulisan
kodenya semakin ringkas. Semuanya akan kita pelajari satu per satu
pada akademi ini.

Pragmatic

Sebuah bahasa pemrograman bisa dikatakan pragmatis jika mampu


mengatasi masalah dengan praktis. Kotlin dikembangkan berdasarkan
permasalahan-permasalahan yang sering dialami oleh programmer di
JetBrains. Tanpa mengesampingkan saran dan feedback dari
komunitas, dalam setiap rilisnya Kotlin selalu memperbarui fitur-fitur
yang ada demi solusi praktis bagi programmer.

Selain ringkas ditulis, hal lain yang membuat Kotlin bisa dikatakan
pragmatis adalah dukungan tools yang sangat membantu proses
penulisan kode. JetBrains menambahkan dukungan Kotlin pada IntelliJ
IDEA beserta plugin-plugin yang disesuaikan dengan setiap fitur yang
ada pada Kotlin.

Plugin yang ada pun mampu menuntun programmer untuk


mempelajari fitur-fitur pada Kotlin. Sebagai contoh, kita bisa
mengkonversi kode Java menjadi Kotlin secara otomatis hanya dengan
melakukan copy-paste kode saja pada berkas Kotlin. Dengan begitu,
secara tidak langsung kita bisa belajar seperti apakah jika sebuah kode
pada Java dituliskan dengan Kotlin. Contoh lain, IntelliJ IDEA mampu
menampilkan peringatan pada sebuah kode yang penulisannya kurang
tepat. Tak hanya itu, setiap peringatan selalu disertai dengan saran
perbaikan. Tentunya kita akan belajar bagaimana seharusnya sebuah
kode dituliskan pada Kotlin.
Pada submodul selanjutnya kita juga akan mempelajari secara lebih
lengkap bagaimana peran IDE dalam mendukung Kotlin sebagai
bahasa yang praktis.

Kotlin Sebagai Bahasa Safe, Statically type..


Safe

Seperti apakah pengertian “aman” dalam sebuah bahasa


pemrograman? Apakah “aman” artinya kita bisa membuat aplikasi
yang tidak mudah dibobol? Tentu tidak. Ketika seorang programer
menuliskan banyak kode untuk membangun aplikasi, akan ada saatnya
programer tersebut bertemu dengan beberapa masalah. Masalah yang
muncul pun bermacam-macam. Mulai dari kode yang eror, proyek tak
berhasil di-build, atau bahkan fitur yang tak berfungsi semestinya.
Apakah ini yang akan kita bahas? Tidak, kita belum akan membahas
masalah-masalah tersebut di sini.

Dengan berjalannya Kotlin di atas JVM, keamanan dari sisi memori


lebih terjamin. Begitu pun keamanan dari sisi masalah lain yang
bersumber dari kesalahan penggunaan memori yang dialokasikan
secara dinamis. Di samping itu Kotlin juga menjamin bahwa tingkat
keamanan lebih tinggi dibandingkan dengan Java. Misalnya, ketika
ingin mendeklarasikan sebuah tipe pada Kotlin, baik tipe data,
argumen, ataupun lainnya, Kotlin mampu menyimpulkan tipe tersebut
secara otomatis. Sehingga kita tidak perlu menuliskannya secara
eksplisit. Tentunya ini akan sangat membantu, karena banyak juga
masalah yang disebabkan oleh kesalahan deklarasi tipe tersebut.

Lebih dari itu, Kotlin mampu memeriksa kesalahan pada saat


kompilasi, sehingga memungkinkan kita untuk mencegah kesalahan
tersebut. Yang paling hebat, Kotlin
menghilangkan NullPointerException yang sering disebut
sebagai “The billion dollar mistake” oleh programer Java. Kotlin
membedakan antara objek yang boleh null atau tidak boleh null pada
saat objek itu dibuat. Tentunya juga menyediakan beberapa solusi
untuk penulisannya. Fitur tersebut dikenal dengan Null Safety.
Sebagai contoh, kode berikut:
Secara default, Kotlin mengasumsikan nilai dari sebuah properti tidak
boleh null. Oleh karena itu, kode pada baris kedua akan langsung
dianggap eror. Namun seringkali kita tidak bisa menghindari bahwa
sebuah data ternyata null, apalagi ketika kita mengkonsumsi data yang
didapatkan dari server. Kita pun bisa menetapkan sebuah
properti nullable dengan menambahkan tanda (?) pada tipe datanya.

Properti a sekarang bisa ditetapkan sebagai nullable, dan untuk


mengaksesnya kita perlu menerapkan sebuah mekanisme untuk
menghindari kesalahan kompilasi. Terdapat beberapa cara yang bisa
dilakukan. Semuanya akan dibahas pada sub-modul terpisah.

Statically Typed

Seperti yang tertulis http://kotlinlang.org dan juga di awal akademi ini,


Kotlin termasuk ke dalam bahasa pemrograman statically typed. Artinya
setiap ekspresi di dalam sebuah program dapat dikenali pada saat
kompilasi. Kompiler juga bisa memastikan bahwa semua fungsi yang
ingin diakses terdapat pada objek yang digunakan. Hal ini berbeda
dengan beberapa bahasa pemrograman lain yang juga berjalan di atas
JVM seperti Groovy dan JRuby. Kedua bahasa tersebut termasuk ke
dalam bahasa pemrograman dynamically typed.

Di sisi lain, jika dibandingkan dengan Java yang juga merupakan


bahasa pemrograman statically typed, Kotlin memungkinkan kita untuk
tidak menuliskan tipe variabel secara eksplisit. Ini akan menghindarkan
kita dari kesalahan seperti salah menuliskan tipe data atau yang
lainnya. Sebagai contoh:

Tanpa menuliskan tipe data String secara eksplisit, kompiler secara


otomatis akan mengetahui bahwa variabel company merupakan
sebuah String. Sebabnya, variabel tersebut diisi dengan nilai String.
Tentunya ini juga membuat kode yang dituliskan menjadi lebih ringkas.
Fitur tersebut dinamakan dengan type inference, yaitu sebuah
mekanisme yang dijalankan oleh kompiler untuk menyimpulkan tipe
dari sebuah context.

Selama ini, terdapat banyak perdebatan mengenai statically


typed atau dynamically typed yang bagus dalam hal produktivitas.
Tentunya banyak juga perbedaan pendapat dari para developer.
Keduanya memiliki keunggulan masing-masing. Berikut adalah
beberapa keunggulan dari bahasa pemrograman statically typed:

 Mengakses sesuatu akan lebih cepat karena kita tidak perlu


mencari tahu fungsi mana yang perlu dipanggil;
 Karena kompiler menjamin kebenaran program, peluang
untuk crash saat runtime akan berkurang;
 Statically typed memungkinkan proses refactoring yang lebih
mudah, apalagi dengan dukungan tool yang hebat seperti auto
complete dan yang lainnya;
 Lebih mudah untuk bekerja dengan relasional database dan
sistem lain yang juga bergantung pada statically typed.

Selain itu, Kotlin juga mendukung function type, yang nanti akan kita
pelajari pada sub-modul functional programming.

Free and Open-Sources

Bagi pegiat open-sources dan developer pada umumnya, hal ini


tentunya sangat menguntungkan. Kompiler, library, tools, dan
terutama Kotlin itu sendiri bebas untuk diakses gratis. Seperti yang
sudah disebutkan di awal akademi, Kotlin mempunyai lisensi Apache
2.0. Anda pun bisa memantau atau berkontribusi untuk
pengembangan Kotlin pada repo-nya
di https://github.com/jetbrains/kotlin . Beberapa IDE yang bisa Anda
gunakan seperti IntelliJ IDEA, Android Studio dan Eclipse juga termasuk
ke dalam open-sources software.

Saat ini sudah terdapat ratusan developer yang berkontribusi dengan


ribuan commit-nya pada pengembangan Kotlin. Jika Anda tertarik
untuk berkontribusi, tersedia juga panduan yang lengkap pada tautan
ini. Semakin banyak kontribusi dari developer-developer hebat,
tentunya Kotlin akan menjadi kian powerful.

Ekosistem Kotlin
Berbicara mengenai ekosistem, di Indonesia sendiri Kotlin mulai ramai
digunakan sejak tahun 2017. Pada tahun itu, Kotlin ditetapkan sebagai
bahasa pemrograman resmi pada salah satu platform yang juga
sangat terkenal, yaitu Android. Walaupun sebenarnya sebelum tahun
2017 juga ada developer yang sudah mulai menuliskan kodenya
dengan Kotlin.

Selain dikenal sebagai bahasa pemrograman yang ringkas dan praktis,


dukungan multiplatform pada Kotlin mampu membuat Kotlin mudah
diterima di berbagai kalangan developer. Untuk developer yang
mempunyai latar belakang sebagai programer Java, C#, JavaScripts,
Scala, maupun Groovy, mereka akan bisa mudah beradaptasi dengan
Kotlin, karena Kotlin memang terinspirasi dari beberapa bahasa
pemrograman tersebut. Beberapa perusahaan besar
seperti Square, Pinterest, Basecamp dan Corda pun sudah
menggunakan Kotlin dan dengan bangga mengumumkannya secara
publik.

Sejak diumumkannya Kotlin sebagai bahasa pemrograman untuk


Android pada Google I/O 2017, tak sedikit developer Android yang
mencoba untuk mempelajari Kotlin. Apalagi di tahun 2019 ini semua
update terbaru pada Android selalu menggunakan Kotlin pada
dokumentasinya. Tentu saja banyak developer Android yang juga
sudah beralih dari Java ke Kotlin. Sepertinya pengumuman dari Google
tersebut sangat berpengaruh terhadap animo developer Android
dalam menggunakan Kotlin. Bahkan sampai ada yang mengira bahwa
Google-lah yang mengembangkan Kotlin.

Tak hanya di luar negeri, di Indonesia pun Kotlin dikenal sangat


melekat dengan Android. Ini ditunjukkan dengan banyaknya developer
yang berdiskusi di komunitas online maupun offline mayoritas adalah
developer Android. Antusiasme developer Android di Indonesia untuk
belajar Kotlin sangatlah besar.

Saat ini, banyak aplikasi yang dikembangkan dengan Kotlin. Mulai dari
startup yang baru mulai dirintis sampai perusahaan yang sudah
memiliki title Unicorn seperti GO-JEK, Tokopedia, dan Bukalapak.
https://developer.android.com/kotlin

Selanjutnya, hal yang juga sangat berpengaruh pada perkembangan


ekosistem Kotlin adalah Komunitas. Baik di luar negeri atau pun di
Indonesia, setiap harinya komunitas online selalu ramai dengan
diskusi-diskusi seputar Kotlin. Tak jarang juga komunitas yang
mengadakan acara offline secara rutin. Ini pertanda komunitas Kotlin,
sangat kuat. Dengan banyaknya developer expert yang peduli
membagikan ilmunya, akan mempermudah teman-teman developer
yang baru untuk mulai belajar Kotlin.

Berikut adalah beberapa kanal komunitas yang bisa Anda ikuti untuk
mendapatkan update rutin seputar Kotlin.

 Kotlin Indonesia
 Kotlinlang
 Antonioleiva.com
 Kotlin Weekly
 Kotlin.link
 The Daily Kotlin
 Talking Kotlin

Banyaknya komunitas yang berkontribusi untuk Kotlin membuat


bahasa tersebut berkembang sangat pesat. Kotlin dinobatkan sebagai
“Fastest growing languages” oleh GitHub Octoverse
2018 mengalahkan Rust, Go, dll.
GitHub Octoverse 2018

Kami harap semoga akademi ini juga bisa berkontribusi untuk


mengembangkan ekosistem Kotlin di Indonesia.

Rangkuman dari Pendahuluan


Kotlin merupakan bahasa pemrograman open-source yang mudah
dipelajari oleh siapapun. Ini bisa dilakukan berkat kejeniusan para
developer di JetBrains yang dipimpin langsung oleh Andrey Breslav.
Selain mudah dipelajari, Kotlin memungkinkan kita untuk membuat
program antar platform yang tentunya ini dapat mengurangi biaya
dalam pembuatan program itu sendiri.

Selain itu dalam sub-modul pendahuluan ini Anda juga telah


mengetahui beberapa hal sebagai berikut:

1. Selain mudah dipelajari, Anda juga dapat ikut berkontribusi di


dalamnya karena Kotlin merupakan project open-source.
2. Kotlin mendukung 2 paradigma (multiparadigm) umum yang
akan Anda sering jumpai, yaitu Object-Oriented Programming
(OOP) dan Functional Programming (FP). Kedua paradigma
tersebut akan sangat membantu proses pengembangan dengan
masing-masing fitur yang dimilikinya.
3. Selain multiparadigm, Kotlin juga
mendukung multiplatform yang berbeda dengan bahasa
pemrograman mainstream lainnya di mana kita dapat membuat
aplikasi mobile (iOS/Android), Web, Desktop, atau Server. Bahkan
Kotlin digadang-gadang bisa digunakan untuk Deep Learning
dengan KotlinDL yang saat ini sudah berstatus alpha!
4. Terdapat 3 bagian pada Kotlin Multiplatform, yaitu

o Common Module
Modul ini berisi kode yang tidak spesifik ke platform apa
pun. Kita bisa menempatkan komponen-komponen yang
bisa digunakan oleh semua modul pada modul ini.
o Platform Module
Pada modul ini kita bisa menambahkan komponen tertentu
yang spesifik untuk satu platform. Biasanya modul ini
merupakan implementasi dari common module.
o Regular Module
Merupakan modul umum yang menargetkan platform
tertentu. Modul ini bisa dependen atau pun menjadi
dependensi dari platform module.
5. Kotlin mendukung dengan baik dan memiliki beberapa kelebihan
dalam mengembangkan aplikasi Android seperti di bawah ini:

o Compatibility
Kotlin sepenuhnya kompatibel dengan JDK 6. Ini
memastikan bahwa aplikasi yang dibangun dengan Kotlin
dapat berjalan pada perangkat Android yang lebih lama
tanpa ada masalah. Android Studio pun mendukung penuh
pengembangan dengan bahasa Kotlin.
o Performance
Dengan struktur bytecode yang sama dengan Java, aplikasi
yang dibangun dengan Kotlin dapat berjalan setara dengan
aplikasi yang dibangun dengan Java. Terdapat juga fitur
seperti inline function pada Kotlin yang membuat kode
yang dituliskan dengan lambda bisa berjalan lebih cepat
dibandingkan kode yang sama dan dituliskan dengan Java.
o Interoperability
Anda dapat menggunakan bahasa Kotlin bersamaan
dengan bahasa Java, tanpa harus memigrasikan semua
kode lama Anda ke Kotlin. Sehingga Anda dapat memanggil
kode Java dari Kotlin dan sebaliknya. Inilah alasan yang
menyebabkan Kotlin menjadi cepat diterima oleh
developer.
o Compilation Time
Kotlin mendukung kompilasi inkremental yang efisien. Oleh
karena itu, proses build biasanya sama atau lebih cepat
dibandingkan dengan Java.
6. Perkembangan Kotlin pada Android pun bisa dibilang sangat
cepat. Bahkan pada acara Google I/O 2019 lalu, Google
mengumumkan Kotlin First!, yaitu menetapkan Kotlin sebagai
bahasa pemrograman nomor 1 (satu) untuk Android. Hampir
semua update pada Android saat ini sudah menggunakan Kotlin
pada dokumentasinya.
7. Berikut ini adalah beberapa karakteristik dari bahasa Kotlin

o Modern and Concise


Kotlin dikenal dengan bahasa modern yang ringkas untuk
dituliskan. Kotlin mampu memangkas berbaris-baris kode
menjadi hanya beberapa baris saja.
o Pragmatic
Sebuah bahasa pemrograman bisa dikatakan pragmatis
jika mampu mengatasi masalah dengan praktis.
o Safe
Anda bisa meminimalisir kesalahan yang sering terjadi
ketika menggunakan Java, yaitu NullPointerException.
o Statically Typed
Artinya setiap ekspresi di dalam sebuah program dapat
dikenali pada saat kompilasi.
o Open source
Anda juga dapat ikut berkontribusi di dalam
pengembangan bahasa Kotlin.
8. Kotlin pernah berada di posisi pertama dalam Fastest growing
languages versi GitHub Octoverse 2018 berkat banyaknya
dukungan komunitas dalam pengembangannya.

Rangkuman di atas merupakan awal dari perjalanan Anda dalam


menyelesaikan kelas ini. Jadi, tetap semangat untuk menuntaskan sub-
modul berikutnya ya!

Membangun dan Menjalankan Program Kotlin


Pada submodul sebelumnya kita sudah berkenalan dengan Kotlin,
mulai dari sejarah, karakteristik yang dimilikinya, hingga ke
ekosistemnya di kalangan developer. Kini saatnya kita masuk topik
selanjutnya. Bagaimana cara untuk membangun dan menjalankan
program Kotlin? Di sini kita akan belajar membuat sebuah program
dari awal dengan hanya memanfaatkan text editor, terminal, dan build
tools, sebelum nantinya menggunakan IDE. Lalu, peralatan apa sajakah
yang kita butuhkan? Mari kita siapkan terlebih dahulu.

Persiapan dan Instalasi


Pada tahap pertama, tentunya kita perlu menyiapkan beberapa tools
yang dibutuhkan untuk membangun program dengan Kotlin. Beberapa
tools itu bisa kita kategorikan ke dalam SDK, IDE, dan build tools.

Software Development Kit (SDK)

SDK merupakan seperangkat alat pengembangan perangkat lunak


yang digunakan untuk mempermudah pengembangan aplikasi dalam
platform tertentu. Setiap platform biasanya menyediakan SDK khusus.
Misalnya, Android dengan Android SDK-nya, iOS dengan iOS SDK-nya,
ataupun Java dengan JDK-nya. Dengan SDK tersebut, developer dapat
mengakses fitur khusus dari masing-masing platform. Terdapat juga
SDK di luar platform seperti Google SDK, Facebook SDK, dll yang bisa
diintegrasikan ke aplikasi.
Untuk Kotlin, karena ia berjalan diatas JVM, maka ia sama seperti Java.
Kotlin menggunakan JDK sebagai SDK-nya dan JRE untuk menjalankan
program aplikasi.

JDK, JRE dan JVM sendiri terlihat sama karena ketiganya merupakan inti
dari bahasa pemrograman Java. Meski terlihat sama, masing-masing
dari ketiganya, punya peran sendiri-sendiri. JDK (Java Development
Kit) adalah sebuah perangkat lunak yang menyediakan
beberapa tools untuk pengembangan dan berkas binary yang
diperlukan untuk proses kompilasi dari kode Java ke bytecode.

Selanjutnya, JVM atau Java Virtual Machine bertanggung jawab untuk


melakukan konversi bytecode ke dalam bahasa mesin. JVM juga
menyediakan fungsi inti dari Java, seperti memory
management, garbage collection, security, dan sebagainya. JVM disebut
virtual karena memiliki antar muka yang tidak bergantung pada sistem
operasi dan perangkat keras yang menjadi dasar dari JVM itu sendiri.

Terakhir, JRE atau Java Runtime Environment merupakan


implementasi dari JVM yang menyediakan sebuah platform untuk
menjalankan program. Berbeda dengan JDK dan JVM, JRE tidak
menyediakan tools untuk pengembangan seperti
kompiler, debugger, dan sebagainya; tetapi JRE diperlukan untuk
menjalankan program.

Pada dasarnya, setiap JDK yang bisa kita gunakan memiliki basis
OpenJDK dan bersifat open-source. Perbedaannya adalah cara JDK
tersebut didistribusikan. Contoh distribusinya bisa dari Oracle
(OracleJDK), OpenJDK Distribution atau Azul Zulu JDK.

Pada kelas ini, kita akan menggunakan JDK yang didistribusikan oleh
OpenJDK Distribution karena bisa digunakan secara gratis dengan
lisensi personal. Nah untuk JRE, kita tidak perlu melakukan instalasi
secara terpisah karena sudah terdapat di dalam paket instalasi
OpenJDK.

Build Tools
Selanjutnya adalah build tools, perangkat lunak yang akan kita gunakan
untuk membantu mengotomatisasi proses. Seperti misalnya
pemaketan dari proyek yang kita akan kembangkan. Selain
kompiler command line dan IntelliJ IDEA, Anda juga dapat
menggunakan Ant, Maven, dan Gradle sebagai build tools-nya. Dari
ketiga build tools tersebut, Gradle-lah yang paling sering digunakan.
Pasalnya, ia cukup fleksibel dalam membantu proses kompilasi.

Gradle sendiri merupakan sebuah perangkat lunak open-sources yang


bisa kita gunakan untuk berbagai macam keperluan dalam
pengembangan aplikasi [3]. Dalam menuliskan skrip Gradle, kita bisa
menggunakan Groovy atau Kotlin DSL. Gradle mendukung proses
pengunduhan dan konfigurasi secara otomatis dari sebuah
dependensi atau library lain. Selain itu, Gradle berfokus pada
fleksibilitas dan kinerja sehingga memungkinkan kita untuk
membangun sebuah aplikasi dengan mudah.

Gradle memiliki beberapa fitur yang cukup penting, seperti performa


yang cukup stabil dan sudah didukung oleh beberapa IDE terkenal
seperti Eclipse, Android Studio dan Intellij IDEA. Untuk mengetahui
lebih dalam tentang keunggulan dalam penggunaan Gradle, silakan
membacanya pada tautan ini.

Integrated Development Environment (IDE)

Proses pengembangan aplikasi tak lepas dari bantuan IDE. Memang


tanpa IDE kita tetap bisa membuat program dengan text
editor. Namun, fitur-fitur yang IDE tawarkan akan membuat proses
pengembangan menjadi jauh lebih mudah dan efisien.

Pada umumnya IDE menyediakan beberapa fitur seperti text


editor yang akan kita gunakan untuk menulis kode, tools untuk
mengotomatisasi proses build dari program yang kita buat dan
sebuah debugger yang akan membantu kita mendeteksi dan
memperbaiki kesalahan yang terdapat pada program. Terdapat
berbagai macam IDE yang mendukung pengembangan dengan bahasa
pemrograman Kotlin seperti IntelliJ IDEA, Android Studio,
dan Eclipse.

Dari semua IDE tersebut, IntelliJ IDEA dan Android Studio-lah yang
paling direkomendasikan. Anda bisa menggunakan IntelliJ IDEA untuk
pengembangan aplikasi secara umum dan Android Studio untuk
pengembangan aplikasi Android.
.
Pada akademi ini, kita akan fokus menggunakan IntelliJ IDEA. IntelliJ
IDEA dikembangkan oleh pengembang yang sama dengan Kotlin, yaitu
JetBrains. Tentunya ada kompatibilitas yang lebih antara keduanya.
Bahkan, JetBrains juga menyediakan tutorial khusus untuk memulai
Kotlin menggunakan IntelliJ IDEA. Anda bisa membacanya di tautan ini.
Dengan dukungan fitur yang mumpuni, IntelliJ IDEA dapat membantu
kita menyelesaikan program yang sedang kita kembangkan dengan
cepat.

Intellij IDEA memiliki dua versi yang dapat kita gunakan untuk
pengembangan aplikasi, yaitu versi Ultimate dan Community. Versi
Ultimate ditujukan untuk pengembangan aplikasi lebih lanjut. Pada
akademi ini, kita akan menggunakan versi Community untuk belajar
Kotlin.

Instalasi OpenJDK (Windows)


Kita telah tuntas membahas sistem operasi Linux dan macOS di
submodul sebelumnya. Dalam submodul ini, kita akan membahas
instalasi dan konfigurasi OpenJDK untuk sistem operasi Windows.
Nah, untuk metode instalasinya sendiri berbeda dengan Linux dan
macOS yang menggunakan SDKMAN. Untuk sistem operasi Windows,
kita akan menggunakan installer yang sudah disediakan. Sebelum itu
mari kita unduh terlebih dahulu berkas instalasinya pada tautan
berikut ini.

Kira-kira tampilan dari halaman untuk mengunduh OpenJDK akan


seperti di atas. Perhatikan bahwa versi dari OpenJDK harus sesuai
dengan spesifikasi arsitektur sistem operasi yang Anda gunakan
(32bit atau 64bit). Pastikan Anda mengunduh berkas yang
berekstensi .msi.

Setelah proses pengunduhan selesai, langsung saja jalankan berkas


instalasi tersebut. Dalam proses instalasi, kita harus mencatat lokasi
dari OpenJDK untuk memudahkan dalam mengonfigurasi OpenJDK itu
sendiri. Lantas bagaimana cara mengetahui lokasi tersebut? Mudah!
Cukup perhatikan lokasi yang tampil pada jendela Destination
Folder seperti di bawah ini.

Dalam gambar di atas, kita bisa tahu bahwa lokasi JDK akan diinstal
pada folder C:\Program Files\Zulu\zulu-8. Jika telah Anda catat,
lanjutkan kembali proses instalasi dengan mengikuti panduan yang
tampil hingga selesai.

Konfigurasi JAVA_HOME

Langkah selanjutnya adalah melakukan konfigurasi lokasi OpenJDK. Ini


bertujuan agar proses instalasi IntelliJ IDEA pada submodul berikutnya
dapat berjalan dengan baik. Anda tidak perlu mengaturnya jika pada
langkah sebelumnya sudah menambahakan variable untuk
JAVA_Home. Namun, jika belum, mari sama-sama kita
konfigurasi OpenJDK dengan mengikuti beberapa langkah berikut.

1. Buka Control Panel kemudian masukkan system variable pada


kolom pencarian.
2. Pilih Edit the system environment variables pada hasil
pencarian.
3. Pada jendela yang tampil, klik tombol Environment
Variables yang berada paling bawah pada jendela yang tampil.
4. Fokus pada bagian System variables, klik tombol New.
5. Setelah terbuka, masukkan JAVA_HOME pada kolom Variable
name dan lokasi instalasi OpenJDK yang sebelumnya sudah
dicatat pada Variable value seperti berikut.

6. Selanjutnya klik OK untuk menutup jendela yang tampil.


7. Jika dirasa sudah sesuai, tutup jendela Environment
Variables dengan mengklik tombol OK. Hasilnya seperti ini.

Catatan: Untuk menambahkan di level System Variable, gunakanlah versi admin (bawah). Jika versi biasa (atas), Anda

Terakhir, untuk memastikan apakah instalasi sudah berhasil, jalankan


perintah "java -version" pada Command Prompt. Pastikan versi
dari Java dapat ditampilkan seperti berikut.
Namun, jika yang tampil ternyata adalah pesan "javac is not
recognized" atau pesan eror lainnya yang menyebabkan tidak
tampilnya versi OpenJDK, pastikan kembali lokasi yang diatur
pada Environment Variable sudah benar. Jika dirasa sudah benar,
tetapi masih menampilkan eror yang sama, cobalah untuk restart
komputer Anda. Namun, jika masih saja terdapat eror, coba
jalankan Command Prompt sebagai administrator. Ini dilakukan
karena OpenJDK berlokasi pada spot yang membutuhkan permintaan
akses saat ingin digunakan.

Instalasi Gradle (Windows)


Instalasi Gradle pada sistem operasi Windows sedikit berbeda dengan
Linux dan macOS karena di sini kita akan melakukannya secara
manual. Mulai dari mengunduh berkas distribusinya, melakukan
konfigurasi, sampai mengecek apakah Gradle sudah berhasil diinstal.
Mari kita mulai dengan mengunduh berkas distribusi yang akan kita
gunakan. Caranya dengan mengikuti beberapa langkah berikut.

1. Unduh berkas distribusi Gradle pada


tautan https://gradle.org/releases/. Anda bisa memilih binary-
only atau complete yang disertai dengan dokumentasi.
Ka
mi menyarankan Anda mengunduh Gradle versi terbaru untuk
menghindari kesalahan yang mungkin saja terjadi.
2. Setelah proses unduhan selesai, ekstrak ke folder yang
diinginkan. Sebaiknya tempatkanlah pada folder yang mudah
dijangkau (misal pada folder utama C:\gradle). Ini akan
mempermudah konfigurasi Environment Variable.

Konfigurasi Environment Variable

Setelah selesai mengekstrak paket distribusi, selanjutnya kita akan


melakukan konfigurasi agar gradle dapat digunakan dengan mudah
dan tentunya untuk menghindari eror saat ingin menggunakannya.
Sama seperti OpenJDK, konfigurasi gradle akan kita lakukan
pada Environment Variable. Oleh karena itu, langsung saja buka
kembali jendela Environment Variable dengan cara seperti yang sudah
kita pelajari pada submodul instalasi OpenJDK.
Saat jendela Environment Variables sudah terbuka, pada
kolom System Variables seperti cuplikan gambar di bawah ini.

Pilih variable path kemudian klik Edit.

Setelah
jendela baru terbuka, Klik tombol New kemudian tambahkan lokasi
dari berkas distribusi Gradle seperti contoh berikut.

 Misalnya file dari zip saya extract ke C:\gradle-x.x.x\ (dengan


'Gradle' adalah folder baru yang saya buat di dalam Program
Files), lalu bukalah folder bin dan copy path dengan cara klik
pada bagian ini terlebih dahulu.

 Kemudian paste seperti berikut.

Catatan: Untuk pengguna Windows 7, perintah di atas akan sedikit berbeda. Tapi tidak perlu khawatir, caranya cukup
tampil seperti di bawah ini:

Tambahkan lokasi paket distribusi Gradle pada baris terakhir yang di awali dengan karakter ; (titik koma). Kurang
setelah ditambahkan.
Setelah selesai, klik OK pada jendela yang tampil dan
jendela Environment Variable. Untuk memastikan apakah gradle
sudah terinstall dengan baik. Anda bisa menjalankan perintah gradle -
v pada command prompt seperti berikut.

Jika terjadi error, pastikan kembali bahwa OpenJDK sudah dikonfigurasi


dan dijalankan dengan baik. Sebabnya, Gradle akan menggunakan
konfigurasi JAVA_HOME yang berada pada pengaturan Environment
Variables.

Untuk instalasi gradle, kita sudah selesai. Materi berikutnya akan


mempelajari bagaimana instalasi IntellIJ IDEA sebagai IDE yang akan
kita gunakan. Penasaran seperti apa langkah-langkahnya? Langsung
saja menuju materi selanjutnya.

Instalasi IntelliJ IDEA


Sebelum melakukan instalasi IntelliJ IDEA, ketahui terlebih dahulu
beberapa syarat di masing-masing sistem operasi sebagai berikut.

 Windows
 macOS
 Linux

 Microsoft Windows 10 atau yang terbaru.


 2 GB RAM minimum, 8 GB RAM direkomendasikan
 3.5 GB minimum ruang kosong pada penyimpanan, 5 GB
direkomendasikan
 1024x768 minimal resolusi layar, 1920×1080 direkomendasikan

Pastikan komputer Anda memenuhi syarat di atas. Jika sudah,


unduhlah berkas instalasi IntelliJ IDEA berdasarkan sistem operasi
dengan versi yang kami sarankan yaitu versi 2023.2.2
Community yang dapat diunduh pada tautan IntelliJ IDEA download
page.

Konfigurasi Intellij IDEA

Pada dasarnya jika sebelumnya komputer kita sudah terinstal JDK, kita
tidak perlu melakukan konfigurasi pada Intellij IDEA. Mengapa
demikian? JDK akan secara otomatis terdeteksi sehingga Anda bisa
langsung menggunakannya untuk membuat proyek baru.

Untuk mengenal IntelliJ IDEA lebih lanjut, Anda bisa membaca blog
berikut: Berkenalan Dengan IntelliJ IDEA
Program Pertama Kotlin
Jika semua tools sudah siap, kini Anda bisa mulai mencoba untuk
membuat dan menjalankan program dengan Kotlin. Seperti yang
sudah disampaikan, Kotlin memiliki dukungan tools yang memadai.
Ketika ingin membuat sebuah program dengan Kotlin, Anda bisa
memilih berbagai macam tools mulai dari yang paling dasar hingga
tingkat lanjut.

Pada dasarnya semua program aplikasi bisa dikembangkan hanya


dengan bantuan text editor dan build tools. Lalu adanya IDE adalah
untuk mempermudah dan mempercepat proses pengembangan. Pada
submodul ini, kita akan mempelajari bersama perihal bagaimana
membuat program dengan Kotlin dari cara yang paling dasar hingga
memanfaatkan bantuan IDE.

Membuat Program Dengan Gradle

Guna membuat program dengan Gradle, kita akan membutuhkan


sebuah plugin yaitu Gradle Init Build Plugin. Kita tidak perlu
menambahkannya secara manual karena plugin tersebut merupakan
bawaan dari paket instalasi Gradle.

Sebelum membuat project, terlebih dahulu buat folder baru yang akan
digunakan sebagai folder project yang nantinya akan kita buat. Setelah
selesai, silakan buka terminal atau command prompt dari dalam
folder tersebut.

Untuk Anda yang menggunakan sistem operasi Windows, gunakan pintasan dengan menulisakan cmd pada search ba
membuka Command Prompt dari dalam folder project seperti berikut:

Setelah terminal atau command prompt terbuka, langsung saja


jalankan perintah gradle init untuk membuat project baru seperti
seperti berikut.
Untuk pembuatan folder project di atas, berilah nama kotlin-starter.
Silakan sesuaikan namanya sesuai kehendak Anda. Lebih lanjut,
setelah kita menjalankan perintah seperti di atas, terminal akan
menampilkan daftar jenis-jenis proyek yang bisa kita pilih. Kita bisa
memilih jenis dari proyek yang ingin kita kembangkan dengan cara
memilih angka yang ada pada daftar tersebut. Karena kita akan
membuat proyek dengan tipe application, masukkan angka 2 dan
tekan enter.

Berikutnya kita akan diminta untuk memilih bahasa yang akan


digunakan. Karena kita akan membuat proyek dengan Kotlin, langsung
saja masukkan angka 4 dan tekan enter. Jika ada pertanyaan tentang
membuat multiple subproject untuk aplikasi, pilih no.
Setelah itu, Anda juga bisa menentukan tipe dari build script, nama
proyek, juga package name, dan Java SDK yang akan digunakan.
Selengkapnya bisa Anda lihat pada gambar berikut.

Sampai di sini kita telah memiliki proyek Kotlin baru dengan


nama kotlin-starter, package name com.dicoding.kotlin dan
menggunakan Kotlin DSL sebagai build script-nya.
Sebenarnya kita bisa meringkas langkah-langkah tersebut dengan cara
langsung menuliskan perintah seperti berikut.

1. gradle init --type kotlin-application --dsl kotlin --project-name

kotlin-starter --package com.dicoding.kotlin

Jika Anda membuka proyek tersebut, Anda akan melihat struktur


proyek seperti di bawah ini.

Mari kita pelajari satu per satu dari masing-masing berkas tersebut.

Gradle Wrapper

Di dalam folder gradle/wrapper/ kita akan menemukan 2 (dua)


berkas, yaitu gradle-wrapper.jar dan gradle-wrapper.properties.
Berkas Wrapper JAR merupakan sebuah library yang berisi kode untuk
mengunduh distribusi Gradle, sedangkan gradle-
wrapper.properties adalah sebuah properti untuk
mengonfigurasi behaviour dari Wrapper runtime seperti mengatur
versi Gradle dari proyek dll. Berikut adalah konfigurasi yang terdapat
pada berkas tersebut:

1. distributionBase=GRADLE_USER_HOME

2. distributionPath=wrapper/dists

3. distributionUrl=https\://services.gradle.org/distributions/gradle-

8.5-bin.zip

4. zipStoreBase=GRADLE_USER_HOME

5. zipStorePath=wrapper/dists

Terdapat juga berkas gradlew dan gradlew.bat pada folder root, yaitu
sebuah shell script dan Windows batch script yang digunakan untuk
menjalankan build dengan Wrapper.

Build Scripts

Selanjutnya, di dalam proyek tersebut juga terdapat 2 (dua)


berkas gradle scripts yaitu settings.gradle.kts dan build.gradle.kts.
Kedua berkas tersebut merupakan Gradle Kotlin DSL yang bisa kita
gunakan untuk mengatur konfigurasi dari Gradle. Gradle mendukung 2
(dua) jenis build script yaitu Groovy dan Kotlin DSL. Namun, pada
akademi ini kita hanya akan fokus menggunakan Kotlin DSL. Beberapa
hal yang menjadi alasan kenapa kita memilih Kotlin DSL adalah sebagai
berikut.

 Memungkinkan kita untuk memaksimalkan fitur auto-


completion pada IDE nantinya.
 Membuat kita tidak perlu mempelajari 2 bahasa (Groovy +
Kotlin).
 Untuk DSL Konfigurasi, pengembangan Gradle kedepan akan
lebih fokus ke penggunaan Kotlin dibandingkan dengan Groovy.
Di dalam berkas settings.gradle.kts, kita akan menemukan konfigurasi
berikut.

1. /*

2. * This file was generated by the Gradle 'init' task.

3. *

4. * The settings file is used to specify which projects to include in

your build.

5. * For more detailed information on multi-project builds, please

refer to

https://docs.gradle.org/8.5/userguide/building_swift_projects.html

in the Gradle documentation.

6. */

7.

8. plugins {

9. // Apply the foojay-resolver plugin to allow automatic download

of JDKs

10. id("org.gradle.toolchains.foojay-resolver-convention") version

"0.7.0"

11. }

12.

13. rootProject.name = "kotlin-starter"


14. include("app")

Konfigurasi tersebut digunakan untuk mengatur nama dari proyek kita.


Ke depannya, kita bisa menambahkan beberapa konfigurasi seperti
pengaturan submodul dan sebagainya di dalam berkas ini.

Kemudian mari kita beralih ke berkas build.gradle.kts.

1. /*

2. * This file was generated by the Gradle 'init' task.

3. *

4. * This generated file contains a sample Kotlin application project

to get you started.

5. * For more details on building Java & JVM projects, please refer to

https://docs.gradle.org/8.5/userguide/building_java_projects.html in

the Gradle documentation.

6. */

7.

8. plugins {

9. // Apply the org.jetbrains.kotlin.jvm Plugin to add support for

Kotlin.

10. alias(libs.plugins.jvm)

11.
12. // Apply the application plugin to add support for building a

CLI application in Java.

13. application

14. }

15.

16. repositories {

17. // Use Maven Central for resolving dependencies.

18. mavenCentral()

19. }

20.

21. dependencies {

22. // Use the Kotlin JUnit 5 integration.

23. testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")

24.

25. // Use the JUnit 5 integration.

26. testImplementation(libs.junit.jupiter.engine)

27.

28. testRuntimeOnly("org.junit.platform:junit-platform-launcher")
29.

30. // This dependency is used by the application.

31. implementation(libs.guava)

32. }

33.

34. // Apply a specific Java toolchain to ease working on different

environments.

35. java {

36. toolchain {

37. languageVersion.set(JavaLanguageVersion.of(21))

38. }

39. }

40.

41. application {

42. // Define the main class for the application.

43. mainClass.set("com.dicoding.kotlin.AppKt")

44. }

45.
46. tasks.named<Test>("test") {

47. // Use JUnit Platform for unit tests.

48. useJUnitPlatform()

49. }

Di dalam berkas tersebut terdapat berbagai macam konfigurasi seperti


pengaturan plugins, repositories, dependencies, dan lain
sebagainya. Biasanya kita akan sering menggunakan berkas ini ketika
ingin menambahkan dependency atau library baru. Pada proyek baru
tersebut kita terdapat beberapa library yang secara otomatis sudah
ditambahkan.

Source (src)

Folder src merupakan tempat kita menyimpan berbagai macam


sumber daya untuk pengembangan aplikasi. Di dalamnya, Anda akan
melihat 2 (dua) folder, yaitu main dan test.

Mari kita mulai dari folder main terlebih dahulu. Folder ini merupakan
folder utama tempat kita meletakkan berkas kode
dan resources lainnya. Di dalam folder main terdapat folder Kotlin
yang di dalamnya juga terdapat package name dari proyek kita
yaitu com.dicoding.kotlin. Pada package name inilah kita bisa
menambahkan berkas kode nantinya. Saat ini, kita sudah memiliki 1
berkas bernama App.kt:

Selanjutnya adalah folder test yang berisi berkas-berkas kode


pengujian aplikasi. Sama dengan folder main, di dalam test juga
terdapat folder kotlin dan package name dari proyek kita. Di sana
terdapat berkas AppTest.kt yang merupakan sebuah kelas pengujian.
Berikut kode di dalamnya.

Semua kode di atas dibuat secara otomatis saat kita membuat proyek
dengan Gradle.
Menjalankan Program Gradle

Setelah mengetahui struktur dari proyek yang dibuat, selanjutnya kita


akan menjalankan program tersebut. Caranya sangat sederhana. Pada
terminal kita cukup menjalankan 1 (satu) perintah Gradle berikut.

1. gradle run

Lalu, Gradle akan melakukan proses build pada proyek tersebut.


Secara otomatis ia akan mengeksekusi kode di dalam berkas App.kt.
Jika berhasil, terminal akan menampilkan pesan seperti di bawah ini.

Jika proses build berlangsung lama, itu adalah hal normal karena baru
pertama kali dijalankan pada suatu proyek di mana compiler akan
mengunduh beberapa library pendukung agar program dapat
dijalankan dengan baik.

Langkah-langkah di atas sama persis ketika kita menggunakan sistem


operasi Windows sehingga kita tidak perlu khawatir. Namun, pastikan
bahwa saat Anda menjalankan perintah gradle init. Perintah tersebut
dijalankan dari dalam folder project baru. Jika dijalankan di dalam
folder project yang sebelumnya sudah menjalankan perintah
tersebut, command prompt akan menampilkan eror dan tak akan
berlanjut ke langkah-langkah berikutnya.
Perintah gradle run di atas juga bisa juga Anda gunakan pada system
operasi Windows. Berikut contoh jika perintah tersebut dijalankan.

Membuat Program dengan IntelliJ IDEA


Di submodul sebelumnya kita sudah belajar bagaimana membuat
proyek baru dengan memanfaatkan perintah dari Gradle. Selanjutnya,
kita akan mencoba membuat proyek baru menggunakan IntelliJ IDEA.
Langsung saja, buka IntelliJ IDEA pada komputer Anda. Berikut adalah
tampilan utama dari IntelliJ IDEA.
Untuk membuat proyek baru, Anda bisa memilih menu New Project.
Anda akan melihat jendela baru kurang lebih seperti berikut.
Beri nama project sesuai keinginan Anda. Untuk konfigurasi lainnya,
biarkan saja sesuai default. Di sini kita membuat project dengan
konfigurasi berikut.

Language Kotlin

Build system Gradle

JDK Amazon Correto 21.x.x

Gradle DSL Kotlin

GroupId com.dicoding.kotlin

Beberapa informasi yang kita masukkan tersebut akan menjadi


identitas project yang akan kita kembangkan. Secara default, Intellij
IDEA sudah menentukan nama proyek (sesuai dengan ArtifactId) dan
juga lokasi proyek. Namun, Anda bisa menggantinya sesuai kebutuhan.
Contohnya perihal JDK, sesuaikan dengan versi JDK yang sudah Anda
instal sebelumnya.

Jika sudah sesuai, klik tombol Create dan Intellij IDEA akan
membuatkan Anda sebuah proyek baru. Berikut adalah tampilan dari
proyek tersebut.

Catatan: pastikan Anda terhubung dengan internet karena dalam


proses pembuatan project akan memperlukannya untuk mengunduh
berkas-berkas yang dibutuhkan.

Menjalankan Program IntelliJ IDEA

Seperti yang sudah disampaikan sebelumnya, salah satu kelebihan


dari menggunakan IDE adalah dukungannya terhadap GUI. Perintah-
perintah yang biasanya mengharuskan kita untuk menuliskannya pada
terminal kini bisa digantikan dengan tombol interaktif pada IDE.
Seperti halnya tombol untuk menjalankan program berikut.
Tombol (run) tersebut hanya akan muncul di samping fungsi
dengan nama main(). Klik tombol tersebut atau tekan Alt + Shift +
F10 pada Windows untuk menjalankan program. Kompiler pada IntelliJ
IDEA akan mengeksekusi kode di dalam fungsi main(). Jika berhasil,
IIntelliJ IDEA akan menampilkan panel Run seperti di bawah ini.

Mantap! Kode kotlin pertama Anda berjalan di Intellij IDEA. Lebih


nyaman menggunakan IDE ini dibandingkan terminal, bukan? Jika Anda
perhatikan pada bagian kiri aplikasi, terdapat kumpulan folder yang
berisi berkas-berkas dalam project tersebut. Dengan bantuan Intellij
IDEA, Anda lebih mudah untuk mengaturnya sesuai kebutuhan.

Rangkuman dari Persiapan Membangun dan Menjalankan Program


Kotlin
Kita sudah selesai dengan persiapan membangun dan menjalankan
program dengan Kotlin. Untuk me-refresh kembali apa yang sudah
dipelajari, berikut adalah rangkumannya.

 Kotlin menggunakan Java Development Kit (JDK) sebagai SDK-nya.


 Terdapat banyak distribusi JDK yang bisa Anda gunakan,
seperti OracleJDK, OpenJDK, Azul Zulu JDK, atau yang lainnya.
 Kotlin berjalan di atas dan mengunakan JVM untuk menjalankan
program yang Anda sudah kembangkan.
 Untuk melakukan otomatisasi seperti proses kompilasi, Anda
akan menggunakan Gradle sebagai build script dalam
pengembangan program.
 Anda bisa menggunakan Groovy atau Kotlin DSL sebagai
gradle build script.
 Dalam proses instalasi JDK dan Gradle di Linux dan macOS, Anda
akan memanfaatkan SDK Manager yang bernama SDKMAN,
sedangkan pada OS Windows menggunakan installer yang sudah
disediakan Azul Zulu JDK.
 Dalam menuliskan kode program, Anda bisa memanfaatkan IDE
yang dikembangkan oleh JetBrains, yaitu Intellij IDEA. Intellij IDEA
terbagi atas 2 (dua) versi, yaitu Ultimate (berbayar)
dan Community (gratis).

 Untuk membuat projek Kotlin, bisa dilakukan dengan 2 (dua) cara


yaitu melalui terminal atau langsung menggunakan IntelliJ IDEA
dengan project wizard-nya.
Setelah melakukan persiapan, sudah siap menuliskan kode
Kotlin? Yuk, kita lanjut ke submodul berikutnya.

Implementasi dari JVM yang menyediakan sebuah platform untuk menjalankan


program adalah ...
Build tools
JRE
JDK
SDK

Pengaturan plugins, repositories, dan dependencies terletak pada berkas ...


setting.gradle
gradle-wrapper.properties
gradle-wrapper.jar
build.gradle

Memory management, garbage collection, dan security merupakan contoh


fungsi inti dari Java yang disediakan oleh ...
JDK
JVM
SDK
JRE

Perangkat lunak yang mendukung proses pengunduhan dan konfigurasi secara


otomatis dari sebuah dependensi atau library lain adalah ...
IDE
JVM
Gradle
SDK

Kotlin Fundamental
Kita sudah tahu cara membangun dan menjalankan program Kotlin.
Kini di sub-modul ini kita akan mempelajari konsep-konsep dasar
(fundamental) pada Kotlin. Kita akan belajar bersama mengenai data
types, function, expression dan juga nullability pada Kotlin.

Hello Kotlin!

Sebelum ke topik-topik fundamental tersebut, mari kita awali dengan


pembahasan tentang program Hello Kotlin!. Pada sub-modul
sebelumnya kita telah berjumpa dengan sebuah proyek yang
menampilkan sebuah teks Hello World! dan juga Hello Kotlin!.

Buat Anda yang pernah belajar pemrograman sebelumnya, tentu tak


asing dengan program ini. Hello World! sering digunakan untuk
menunjukkan sintaks dasar pada sebuah bahasa pemrograman.
Karena kita sedang belajar bahasa pemrograman Kotlin, maka kita
mengganti namanya dengan Hello Kotlin!.

Hello Kotlin! merupakan sebuah program sederhana yang digunakan


untuk mencetak sebuah teks “Hello Kotlin!” ke dalam layar atau
konsol. Berikut adalah contoh kode dari program tersebut:

// main function

fun main() {

println("Hello Kotlin!")
}

Baris pertama dari kode di atas adalah komentar yang ditandai dengan
tanda //.

// main function

Sebuah komentar akan dilewatkan ketika proses kompilasi, sehingga


tidak akan mempengaruhi alur program yang kita tulis. Komentar bisa
kita gunakan untuk mendokumentasikan kode yang kita tulis agar
ketika suatu saat kita membukanya kembali, kita bisa mengetahui
fungsi dari kode yang kita beri komentar tersebut.

// single line comment

Terdapat dua jenis komentar yang bisa kita gunakan. Pertama


adalah single line comment yaitu komentar satu baris yang diawali
dengan tanda // dan berakhir di akhir baris komentar tersebut.

Yang kedua adalah multi-line comment yang diawali dengan


tanda /* dan diakhiri dengan tanda */.

/*

multi line comment

Hello Kotlin

*/

Dengan multi-line comment kita bisa menuliskan beberapa baris


komentar.

Selanjutnya adalah fungsi yang bernama main(), fungsi yang wajib kita
definisikan ketika membuat sebuah program.
Fungsi main() merupakan sebuah entry point yang otomatis akan
dipanggil ketika program dijalankan. Pada sub-modul berikutnya kita
akan belajar lebih dalam tentang bagaimana mendefinisikan sebuah
fungsi.
Kemudian fungsi println(), fungsi yang akan kita gunakan untuk
mencetak teks ke dalam layar atau konsol.
Fungsi println() membutuhkan satu argumen berupa message dengan
tipe data yang dikehendaki. Tipe data yang didukung untuk kita
masukkan ke dalam fungsi println() ada di tautan ini.

Selain fungsi println(), terdapat juga fungsi print() yang berfungsi sama
seperti fungsi println(). Bedanya, println() akan menambahkan baris
baru setelah selesai mencetak argumen yang diberikan, sementara
fungsi print() tidak melakukan apapun ketika argumen yang diberikan,
selesai dicetak. Untuk memahaminya lebih dalam, coba jalankan kode
berikut:

fun main() {

val name = "Alfian"

print("Hello my name is ")

println(name)

print(if (true) "Always true" else "Always false")

/*

output:

Hello my name is Alfian

Always true

*/

Fungsi println() dan print() secara internal memanggil


fungsi system.out.print(message).
@kotlin.internal.InlineOnly

public actual inline fun print(message: Any?) {

System.out.print(message)

Kegunaan utama dari fungsi system.out.print(message) adalah untuk


menampilkan pesan yang diberikan ke standard output stream. Selain
menampilkan pesan yang diberikan secara eksplisit, fungsi tersebut
juga dapat digunakan untuk menampilkan nilai dari
sebuah expression atau variabel seperti yang dicontohkan di atas.

Data Types & Variable


Data types atau tipe data adalah sebuah pengklasifikasian data
berdasarkan jenis data tersebut. Untuk mengembangkan sebuah
program, ada beberapa tipe data yang akan kita pelajari. Di antaranya
adalah Character, String, Array, Numbers, dan Booleans. Semuanya
akan kita bahas sejelas dan sesederhana mungkin di dalam submodul
ini.

Namun, ada satu hal yang kita perlu tahu terlebih dahulu,
yaitu Variabel. Umumnya variabel digunakan untuk menyimpan
informasi atau nilai yang akan dikelola di dalam sebuah program.
Sebuah variabel akan membutuhkan kata
kunci var atau val, identifier, type, serta initialization. Kira-kira
strukturnya seperti berikut.

var identifier: Type = initialization

Berikut adalah contoh variable yang bisa diubah nilainya


bernama company dan memiliki nilai "Dicoding" dengan tipe String.

var company: String = "Dicoding"

Mari kita ulas setiap bagian pada struktur variabel di atas.


 var atau val
var atau val digunakan untuk mengontrol nilai dari sebuah
variabel. Dengan kata kunci var, kita bisa mengubah nilai yang
sudah diinisialisasikan.Berikut contohnya.

var company: String = "Dicoding"

company = "Dicoding Academy"


Variabel company yang awalnya memiliki
nilai “Dicoding” sekarang sudah diubah menjadi “Dicoding
Academy”. Ketika menggunakan kata kunci val, kita tidak bisa
mengubah nilai yang sebelumnya sudah diinisialisasi. Jika kita
memaksa untuk mengubahnya, akan terjadi eror seperti berikut.

val company: String = "Dicoding"

company = "Dicoding Academy" // Val cannot be


reassigned
Seperti inilah gambarannya jika diilustrasikan.

 Identifier
Identifier merupakan nama dari sebuah variabel. Pada contoh
kode di atas yang merupakan identifier adalah company. Perlu
diketahui bahwa di dalam sebuah program, kita tidak bisa
membuat lebih dari 1 (satu) variabel dengan nama sama.
 Type
Pada bagian inilah kita menentukan tipe data dari variabel
tersebut. Tipe data dibutuhkan agar kompiler dapat mengetahui
bagaimana sebuah data akan digunakan. Tipe data dari contoh
variabel di atas adalah String. Karena Kotlin mendukung type
inference, kita diperbolehkan untuk tidak menuliskan tipe data
secara eksplisit.

val company = "Dicoding"

 Initialization

Dan yang terakhir adalah initialization atau nilai awal dari sebuah
variabel. Pada contoh di atas, yang berperan
sebagai initialization adalah “Dicoding” dan “Dicoding
Academy”.
Tipe data juga menentukan operasi apa saja yang dapat dilakukan
pada sebuah variabel dan bagaimana nilai dari sebuah variabel
disimpan. Contoh, ketika kita menggunakan operator + terhadap dua
variabel yang bertipe String seperti berikut.

fun main() {

val firstWord = "Dicoding "

val lastWord = "Academy"

print(firstWord + lastWord)

/*

output: Dicoding Academy

*/

Pada kode di atas, kedua nilai dari


variabel firstWord dan lastWord akan digabungkan menjadi satu nilai
string. Berbeda ketika kita menggunakan operator + pada variabel
yang bertipe Int seperti berikut.

fun main() {

val valueA: Int = 10

val valueB = 20

print(valueA + valueB)

/*

output: 30

*/

Kompiler akan menjalankan operasi aritmetika seperti pada contoh di


atas di mana nilai dari variabel valueA dan valueB akan dijumlahkan
lalu menghasilkan nilai baru.

Selain operator tambah (+), ada juga operator lain yang perlu Anda
ketahui untuk memudahkan dalam menuliskan kode Kotlin. Berikut
beberapa di antaranya.

1. +, -, *, /, dan % adalah operator matematika. Anda bisa


mengelola variabel bertipe angka dengan berbagai operator
matematika yang ada.
2. = adalah operator penugasan. Biasanya digunakan untuk
menentukan nilai dari sebuah variabel.
3. +=,-=, *=, /=, dan %=adalah operator penugasan yang
menggabungkan konsep matematika.

// Awalnya dari seperti ini.

var value = 1
value = value + 2

// Menjadi seperti ini.

var anotherValue = 1

anotherValue += 2

// Nilai value dan anotherValue akan bernilai sama, yakni 3

4. &&, ||, dan ! adalah operator logika. Operator AND (&&) dan OR
(||) digunakan untuk membandingkan dua nilai sesuai dengan
kondisi yang Anda inginkan. Berbeda dengan operator NOT (!),
biasanya ia digunakan untuk melakukan negasi pada value yang
ada.
5. ++ dan -- adalah operator increment dan decrement yang untuk
menambah atau mengurangi satu nilai.

Tentunya masih banyak simbol spesial dan operator yang bisa Anda
gunakan dalam membangun kode dengan Kotlin. Anda bisa melihat
selengkapnya di Keyword di Kotlin.

Char
Ketika kita mengembangkan sebuah program kita pasti membutuhkan
variabel dengan tipe data yang mampu menyimpan nilai berbentuk
teks. Terdapat dua (2) tipe data yang bisa kita gunakan,
yaitu Char dan String.

Char
Characters direpresentasikan menggunakan tipe Char. Untuk
mendefinisikan sebuah variabel dengan tipe data Char kita bisa
menggunakan tanda kutip tunggal (' ') seperti berikut:

val character = 'A'

Tipe data Char hanya dapat kita gunakan untuk menyimpan karakter
tunggal. Sebaliknya jika kita memasukkan lebih dari 1 (satu) karakter,
akan terjadi eror:

val character: Char = 'ABC' // Incorrect character literal

Yang menarik, kita bisa melakukan operasi increment (++)


dan decrement (--) pada sebuah variabel dengan tipe data Char seperti
berikut:

fun main() {

var vocal = 'A'

println("Vocal " + vocal++)

println("Vocal " + vocal++)

println("Vocal " + vocal++)

println("Vocal " + vocal--)

println("Vocal " + vocal--)

println("Vocal " + vocal--)

println("Vocal " + vocal--)

/*
output:

Vocal A

Vocal B

Vocal C

Vocal D

Vocal C

Vocal B

Vocal A

*/

Operasi increment dan decrement sendiri merupakan operasi yang bisa


kita gunakan pada tipe data Number. Lalu kenapa kita bisa
menggunakannya pada tipe Char? Karena pada dasarnya setiap
Characters merupakan representasi dari Unicode. Contoh
Unicode A adalah 0041. Ketika kita melakukan increment maka hasilnya
adalah 0042 yang mana merupakan Unicode dari B.

String
String merupakan tipe data yang mirip dengan Char. Ia dapat
digunakan untuk menyimpan nilai berupa teks. Perbedaannya, String
bisa menampung beberapa karakter di dalamnya.

String direpresentasikan menggunakan tipe String. Nilai yang berada di


dalam sebuah variabel dengan tipe data String merupakan kumpulan
dari beberapa karakter. Kita bisa mendefinisikan variabel tersebut
dengan tanda petik ganda (" ") seperti berikut.

val textString = "Kotlin"

Pada dasarnya sekumpulan karakter dalam String tersebut berbentuk


Array sehingga kita bisa mendapatkan karakter tunggal dengan
mudah.
Caranya, manfaatkan indexing seperti berikut.

fun main() {

val text = "Dicoding"

val firstChar = text[3]

print("The 4th character of the $text is $firstChar")

/*

output : The 4th character of the Dicoding is o

*/

Apa itu Indexing?


Indexing merupakan sebuah cara yang memudahkan kita untuk
mengakses elemen yang berada di dalam sebuah Collection dengan
memanfaatkan index atau posisi dari elemen tersebut. Posisi dari
sebuah elemen pada umumnya dimulai dari angka 0. Untuk materi
tentang Collection akan sama-sama kita pelajari pada submodul
berikutnya. Semangat!
Nilai 0 yang berada pada indexing di atas adalah posisi karakter yang
akan diakses. Selain itu, kita juga dapat melakukan iterasi terhadap
objek String dengan menggunakan for-loop seperti berikut.
fun main() {

val text = "Kotlin"

for (char in text){

print("$char ")

/*

output : K o t l i n

*/

Escaped String

Kotlin memiliki dua jenis tipe Literal String, yaitu Escaped


String dan Raw String. Mari kita mulai pembahasannya dari Escaped
String terlebih dahulu.

Escaped String memungkinkan kita untuk mengurangi ambiguitas


nilai yang berada di dalam sebuah String. Misalnya, ketika kita
mendefinisikan sebuah String berikut.

val statement = "Kotlin is Awesome!"

Kemudian, kita ingin menambahkan tanda petik ganda di dalam


sebuah String seperti berikut.
val statement = "Kotlin is "Awesome!""

Maka akan terjadi ambiguitas nilai pada variabel statement karena


kompiler tidak dapat mengetahui akhir dari baris nilai untuk
variabel statement. Untuk mengatasinya, kita bisa
melakukan escaped dengan menambahkan karakter backslash (\)
sebelum tanda petik ganda seperti berikut:
val statement = "Kotlin is \"Awesome!\""
Selain \” di atas, terdapat beberapa karakter lain yang dapat digunakan
untuk melakukan escaped di dalam sebuah String, antara lain:

 \t: menambah tab ke dalam teks.


 \n: membuat baris baru di dalam teks.
 \’: menambah karakter single quote kedalam teks.
 \”: menambah karakter double quote kedalam teks.
 \\: menambah karakter backslash kedalam teks.

Selain itu, kita juga bisa menambahkan sebuah Unicode ke dalam


sebuah String seperti berikut.

fun main() {

val name = "Unicode test: \u00A9"

print(name)

/*

output: Unicode test : ©

*/

Raw String

Setelah membahas Escaped String, kita akan beralih ke Raw


String yang memungkinkan untuk menuliskan multiline dan arbitrary
text. Ketika ingin membuat beberapa baris String, biasanya kita
melakukan escaped terhadap String dengan memanfaatkan
karakter escape \n seperti berikut.

val line = "Line 1\n" +

"Line 2\n" +

"Line 3\n" +

"Line 4\n"

Dengan Raw String, kita dapat membuatnya dengan cara yang lebih
mudah yaitu seperti berikut.
fun main() {

val line = """


Line 1

Line 2

Line 3

Line 4

""".trimIndent()

print(line)

/*

output:

Line 1

Line 2

Line 3

Line 4

*/

Pada kode di atas, kita mendefinisikan sebuah Raw String


menggunakan triple quote (""" """). Raw String memungkinkan kita
untuk membuat beberapa baris String tanpa penggabungan
(concatenation) dan penggunaan karakter escaped. Lebih lanjut, kita
menggunakan metode trimIndent() untuk menghilangkan indentasi
yang kita gunakan pada kode.

String Template
Di beberapa sub-modul sebelumnya Anda sudah melihat bagaimana
sebuah String ditulis seperti berikut:
"First character of $text is $firstChar"

Lantas dinamakan apakah mekanisme penulisan String seperti di atas?


Kotlin mendukung sebuah fitur bernama String Template. Sebuah
fitur yang memungkinkan kita untuk menyisipkan sebuah variabel ke
dalam sebuah String tanpa concatenation (penggabungan objek String
menggunakan +) seperti berikut:
val name = "Kotlin"

print("My name is " + name)

/*

output : My name is Kotlin

*/

Untuk menggunakan string template, kita hanya perlu menambahkan


karakter $ sebelum nama variabel yang akan disisipkan seperti berikut:
val name = "Kotlin"

print("My name is $name")

/*

output : My name is Kotlin

*/

Variabel yang dapat disisipkan tidak sebatas String. Kita juga bisa
menyisipkan objek lain misal Int atau Double seperti berikut:
val name = "Kotlin"

val old = 3

print("My name is $name, im $old years old")

/*

output : My name is Kotlin, im 3 years old

*/

Tidak hanya sampai disitu, Anda juga bisa menyisipkan


sebuah expression ke dalam sebuah string template. Caranya,
sisipkan expression ke dalam curly braces yang diikuti karakter $.
val hour = 7

print("Office ${if (hour > 7) "already close" else "is open"}")

/*

output : Office is open


*/

Dengan string template, kita lebih mudah membuat objek String yang
dinamis.

If Expressions
Saat mengembangkan sebuah program, kita pasti bertemu dengan
alur program yang perlu sebuah kondisi untuk menjalankan
sebuah statement atau expression. Contoh ketika kita ingin
menginisialisasi nilai dari sebuah variabel berdasarkan suatu kondisi.
Untuk menyelesaikannya, gunakan If Expression.

If expression direpresentasikan dengan kata kunci if. If akan kita


perlukan untuk menyelesaikan kasus di atas, dimana if akan digunakan
untuk menguji suatu kondisi untuk menjalankan sebuah proses. If
akan mengeksekusi sebuah statement atau expression jika hasil evaluasi
dari expressions yang diberikan pada blok if bernilai true. Sebaliknya,
jika bernilai false maka proses yang ditentukan akan dilewatkan.

val openHours = 7

val now = 20

if (now > openHours){

println("office already open")

Kode di atas adalah contoh sederhana penggunaan if dengan


memanfaatkan operator greater than untuk membandingkan nilai. Jika
if digunakan untuk mengembalikan nilai atau menetapkan nilai dari
sebuah variabel maka if wajib memiliki branch else. Contohnya seperti
berikut:
val openHours = 7

val now = 20

val office: String

if (now > openHours) {

office = "Office already open"

} else {

office = "Office is closed"


}

print(office)

Else akan dijalankan jika hasil evaluasi pada expression yang diberikan
menghasilkan nilai false. If merupakan sebuah expressions yang dapat
mengembalikan nilai, sehingga kita dapat menyimpan hasilnya ke
dalam sebuah variabel.
val openHours = 7

val now = 20

val office: String

office = if (now > openHours) {

"Office already open"

} else {

"Office is closed"

print(office)

Pada kode di atas, kita hanya menggunakan If untuk menguji 2 (dua)


kondisi. Lalu bagaimana jika kita memiliki beberapa kondisi? Kita bisa
menggabungkan else dan if seperti berikut:
val openHours = 7

val now = 7

val office: String

office = if (now > 7) {

"Office already open"

} else if (now == openHours){

"Wait a minute, office will be open"

} else {

"Office is closed"

}
print(office)

Blok else if akan dijalankan jika hasil evaluasi pada branch sebelumnya
bernilai false. Jika hasil evaluasi pada branch else if juga bernilai
nilai false, maka lanjut ke evaluasi branch selanjutnya.

Perlu diketahui bahwa Kotlin tidak mendukung ternary


operator (condition ? then : else), karena peran dari operator tersebut
sudah digantikan dengan if expressions.

Boolean
Pada submodul sebelumnya, kita telah belajar tentang If
expressions yang menggunakan Boolean expressions. Lalu, apa
itu Boolean? Boolean adalah sebuah tipe data yang hanya memiliki
dua nilai, yaitu true dan false. Terdapat 3 (tiga) operator yang dapat
digunakan pada Boolean.
Conjunction atau AND (&&)

Operator AND (&&) akan mengembalikan nilai true jika semua hasil
evaluasi expression yang diberikan bernilai true.

val officeOpen = 7

val officeClosed = 16

val now = 20
val isOpen = if (now >= officeOpen && now <= officeClosed){

true

} else {

false

print("Office is open : $isOpen")

/*

Output : Office is open : false

*/

Cara membaca kode di atas adalah sebagai berikut.

 Membuat sebuah variabel bernama isOpen dengan tipe data


Boolean.
 Variabel isOpen akan bernilai true (1) ketika nilai
variabel nowlebih besar sama dengan (>=)
variabel officeOpen dan (&&) variabel nowlebih kecil sama
dengan (<=) variabel officeClosed.
 Variabel isOpen akan bernilai false (0) ketika kondisi sebelumnya
tidak terpenuhi.

Fungsi di atas menguji apakah jam sekarang berada di antara jam


waktu buka kantor dan jam tutup kantor. If expressions di atas bisa
Anda sederhanakan menjadi seperti berikut.

val isOpen = now >= officeOpen && now <= officeClosed

print("Office is open : $isOpen")

/*

Output : Office is open : false

*/

Disjunction atau OR (||)


Berbeda dengan operator AND (&&), operator OR (||) akan
mengembalikan nilai true jika hasil evaluasi dari salah
satu expressions yang diberikan bernilai true.
val isClose = now < officeOpen || now > officeClosed

print("Office is closed : $isClose")

/*

Output : Office is closed : true

*/

Variabel isClose di atas bernilai true. Alasannya, hasil evaluasi salah


satu expression yang diberikan, bernilai true, yaitu expression disebelah
kanan.
Negation atau NOT (!)

Berbeda dengan operator AND (&&) dan operator OR(||), operator


NOT(!) digunakan untuk melakukan negasi pada hasil
evaluasi expression yang diberikan. Contoh, Jika
hasil expressions setelah dievaluasi bernilai true, operator NOT akan
mengembalikan nilai false.

if (!isOpen) {

print("Office is closed")
} else {

print("Office is open")

/*

Output : Office is open

*/

Hasil evaluasi expression di atas adalah true. Namun, ketika


menggunakan operator NOT, hasilnya akan dinegasikan menjadi
nilai false sehingga statement pada branch else-lah yang akan
dijalankan.

Numbers
Pada sub-modul tipe data kita sudah mempelajari tentang beberapa
tipe seperti Character dan String . Sekarang kita akan mempelajari
beberapa tipe data yang termasuk ke dalam tipe Number. Number
adalah sebuah tipe data yang khusus digunakan untuk menyimpan
nilai dalam bentuk numerik.

Di Kotlin, tipe data Number disimpan dengan cara yang berbeda.


Beberapa tipe bawaan yang merepresentasikan Numbers
adalah Double, Long, Int, Short dan Byte. Setiap tipe data Number
memiliki ukuran (satuan Bit) berbeda-beda, tergantung besaran nilai
yang dapat simpan.

 Int (32 Bit)

Int adalah tipe data yang umumnya digunakan untuk menyimpan


nilai numerik. Int dapat menyimpan data dari range -2^31 sampai
+2^31-1. Dengan ukuran 32 Bit kita bisa menggunakannya untuk
menyimpan nilai yang besar. Catatannya, tetap lihatlah batasan
nilai maksimal yang dapat dimasukkan.
val intNumber = 100
Long (64 Bit)
Long adalah tipe data yang digunakan untuk menyimpan nilai numerik
yang lebih besar yaitu dari range -2^63 sampai +2^63-1. Long bisa
didefinisikan secara eksplisit:

val longNumber: Long = 100


Atau dengan menambahkan suffix L seperti berikut:
val longNumber = 100L
Short (16 Bit)

Short merupakan sebuah bilangan bulat yang hanya dapat menyimpan


nilai yang kecil karena hanya berukuran 16 Bit.
val shortNumber: Short = 10
Byte (8 Bit)

Dengan ukuran yang kecil, Byte hanya mampu menyimpan nilai yang
kecil sama halnya seperti Short. Byte biasa digunakan untuk keperluan
proses membaca dan menulis data dari sebuah stream file atau
jaringan.
val byteNumber = 0b11010010
Double (64 Bit)

Sama halnya dengan Long yang memiliki ukuran yang besar, Double
mampu menyimpan nilai numerik yang besar pula. Pada umumnya
Double digunakan untuk menyimpan nilai numerik pecahan sampai
dengan maksimal 15-16 angka di belakang koma.
val doubleNumber: Double = 1.3
Float (32 Bit)

Sama seperti Double, namun memiliki ukuran yang lebih kecil, yakni
hanya sampai 6-7 angka di belakang koma.
val floatNumber: Float = 0.123456789f // yang terbaca hanya
0.1234567
Untuk mengetahui nilai maksimal yang dapat disimpan oleh
suatu tipe Number, kita bisa menggunakan
properti MAX_VALUE. Sementara untuk mengetahui nilai minimal
yang dapat disimpan, gunakan properti MIN_VALUE.
val maxInt = Int.MAX_VALUE
val minInt = Int.MIN_VALUE
println(maxInt)
println(minInt)

/*
output :
2147483647
-2147483648
*/
Jika kita memasukan nilai melebihi nilai maksimal yang dapat
disimpan, maka akan terjadi overflow. Nilai yang akan
dikembalikan adalah nilai minimal yang dapat disimpan.
val maxInt = Int.MAX_VALUE
val overRangeInt = Int.MAX_VALUE + 1 // This operation has led to
an overflow

println("Max Int: $maxInt")


println("Over range Int: $overRangeInt")

/*
Output :

Max Int: 2147483647


Over range Int: -2147483648
*/
Terdapat beberapa operator matematika pada tipe data Number
seperti penjumlahan (+), pengurangan (-), perkalian (*) ,
pembagian (/) dan modulus (%, atau sisa hasil bagi).
val numberOne = 1
val numberTwo = 2

print(numberOne + numberTwo)

/*
output : 3
*/
Perlu diketahui, hasil operasi pembagian pada tipe data Int akan
dibulatkan kebawah. Contohnya seperti berikut:
val numberOne: Int = 27
val numberTwo: Int = 10

print(numberOne / numberTwo)

/*
output : 2
*/
Sama seperti perhitungan matematika di mana operasi perkalian
dan pembagian didahulukan, demikian halnya perhitungan pada
Kotlin.
print(5 + 4 * 4)

/*
output: 21
*/
Operasi 4 * 4 akan dilakukan terlebih dahulu, kemudian diikuti 5
+ 16. Jika ingin operasi 5 + 4 dilakukan terlebih dahulu, gunakan
tanda kurung:
print((5 + 4) * 4)

/*
output: 36
*/
Di Kotlin kita tidak bisa melakukan konversi secara langsung.
Contoh, ketika ingin melakukan konversi dari tipe data Byte ke
tipe data Int.
Untuk mengatasinya, lakukan konversi dengan bantuan
beberapa fungsi seperti toInt() berikut:
val byteNumber: Byte = 10
val intNumber: Int = byteNumber.toInt() // ready to go
Kode di atas menggunakan fungsi toInt() untuk melakukan konversi
secara eksplisit dari tipe data Byte ke tipe data Int. Adapun beberapa
fungsi konversi yang dapat kita gunakan antara lain:

 toByte(): Byte
 toShort(): Short
 toInt(): Int
toLong(): Long
 toFloat(): Float
 toDouble(): Double
 toChar(): Char
Contoh lain penggunaan konversi adalah sebagai berikut:

val stringNumber = "23"


val intNumber = 3

print(intNumber + stringNumber.toInt())
/*
output: 26
*/
Dengan fungsi konversi di atas, nilai 23 yang semula bertipe String di
konversi ke tipe Int yang kemudian dimasukan ke dalam operasi
matematika.

Dengan Kotlin kita juga bisa menuliskan nilai numerik yang “readable”
dengan menggunakan tanda underscores seperti berikut:

val readableNumber = 1_000_000


print(readableNumber)

/*
output : 1000000
*/

Arrays
Selanjutnya adalah Array, yakni tipe data yang memungkinkan kita
untuk menyimpan beberapa objek di dalam sebuah variabel. Array di
Kotlin direpresentasikan oleh kelas Array yang memiliki
fungsi get dan set serta properti size. Untuk membuat sebuah Array
kita bisa memanfaatkan sebuah library function arrayOf() seperti
berikut:
val array = arrayOf(1, 3, 5, 7)
Kita juga dapat memasukkan nilai dengan berbagai jenis tipe data ke
dalam arrayOf() misalnya:
val mixArray = arrayOf(1, 3, 5, 7 , "Dicoding" , true)

Kotlin juga memungkinkan kita untuk membuat Array dengan tipe data
primitif dengan memanfaatkan beberapa fungsi spesifik berikut:

intArrayOf() : IntArray
 booleanArrayOf() : BooleanArray
 charArrayOf() : CharArray
 longArrayOf() : LongArray
 shortArrayOf() : ShortArray
 byteArrayOf() : ByteArray
Jika kita ingin membuat Array yang hanya bisa dimasukkan nilai
dengan tipe data Int, gunakan intArrayOf(), misalnya:

val intArray = intArrayOf(1, 3, 5, 7)

Kita juga bisa mendapatkan nilai tunggal dari sekumpulan nilai yang
berada di dalam sebuah Array dengan memanfaatkan indexing seperti
berikut:
val intArray = intArrayOf(1, 3, 5, 7)

print(intArray[2])

/*

Output: 5

*/

Nilai 2 pada kode di atas merupakan indeks atau posisi dari nilai
tunggal yang ingin kita dapatkan. Perlu diketahui bahwa sebuah indeks
selalu dimulai dari 0. Selain mendapatkan nilai tunggal,
dengan indexing kita juga bisa mengubah nilai tunggal tersebut.
Sebagai contoh:
val intArray = intArrayOf(1, 3, 5, 7) // [1, 3, 5, 7]

intArray[2] = 11 // [1, 3, 11, 7]

print(intArray[2])
/*

Output: 11

*/

Nullable Types
Ketika mengembangkan sebuah program, ada satu hal yang tak boleh
kita abaikan. Ia adalah NullPointerException (NPE), sebuah kesalahan
yang terjadi saat ingin mengakses atau mengelola nilai dari sebuah
variabel yang belum diinisialisasi atau variabel yang bernilai null.
Karena sangat umum terjadi dan bisa berakibat fatal, NPE terkenal
dengan istilah “The Billion Dollar Mistake”.

Dalam penanganannya, kita harus berhati-hati karena NPE


menyebabkan aplikasi yang kita kembangkan menjadi rusak saat
dijalankan.

Pada Kotlin, kita dimudahkan untuk mengelola


variabel nullable sehingga dapat meminimalisasi
terjadinya NullPointerException. Kotlin hadir dengan
penanganan nullability yang mudah. Kotlin mampu membedakan objek
yang boleh bernilai null dan objek yang tidak boleh bernilai null pada
saat objek tersebut dibuat.

val text: String = null // compile time error

Kotlin akan memaksa kita untuk menentukan nilai awal dari sebuah
objek ketika dibuat dan tidak boleh bernilai null. Jika ingin sebuah
objek bisa bernilai null, kita bisa menambahkan tanda ? setelah
menentukan tipe dari objek tersebut.
val text: String? = null // ready to go

Namun, kita tidak bisa langsung mengakses atau mengelola nilai dari
objek yang sudah ditandai sebagai nullable. Contohnya sebagai berikut.
val text: String? = null

val textLength = text.length // compile time error


Ketika kita menuliskan kode di atas, ia akan gagal dikompilasi dengan
log eror berikut.

Error:(4, 26) Kotlin: Only safe (?.) or non-null asserted (!!.) calls are
allowed on a nullable receiver of type String?

Lalu, bagaimana cara kita mengakses atau mengelola nilai dari objek
yang ditandai sebagai nullable? Cara mudahnya, periksa objek tersebut
bernilai null atau tidak menggunakan if.

var string: String? = "Dicoding"

if(string != null) { // smart cast

print(string.length) // It works now!

Dengan cara tradisional menggunakan if/else seperti di atas, kompiler


akan mengizinkan kita untuk mengelola nilai dari sebuah variabel yang
kita tandai sebagai nullable. Ia akan otomatis mengubah tipe
data String? menjadi String. Inilah yang disebut dengan fitur Smart
Cast pada Kotlin.

Selain itu, Anda juga bisa menggunakan is atau !is untuk memastikan
sebuah variabel. Compiler akan memastikan tipe data dari variabel
tersebut. Contohnya sebagai berikut.

Pada contoh kode di atas, Kotlin akan secara otomatis mengubah tipe
data Any menjadi String tanpa perlu dikonversi secara manual. Namun,
perlu diperhatikan bahwa bahwa Smart Cast hanya berfungsi jika
kompiler dapat menjamin bahwa variabel tidak akan berubah ketika
setelah diperiksa dan sebelum digunakan.

Oke, sebenarnya ada cara yang lebih elegan untuk penanganan objek
yang ditandai sebagai nullable, yaitu dengan menggunakan Safe
Calls dan Elvis Operator di Kotlin. Seperti apa itu? Mari kita simak di
submodul selanjutnya!

Safe Calls dan Elvis Operator


Di submodul sebelumnya kita sudah mengenal
tentang NullPointerException dan cara penanganannya. Kini kita
akan belajar bagaimana menangani objek nullable dengan cara yang
lebih mudah, yaitu menggunakan Safe Calls dan Elvis Operator.

Safe calls operator (?.)

Yang pertama akan kita pelajari adalah Safe Calls. Seperti


namanya, safe call akan menjamin kode yang kita tulis aman
dari NullPointerException. Dalam menggunakan safe call, kita akan
mengganti tanda titik (.) dengan tanda (?.) saat mengakses atau
mengelola nilai dari objek nullable seperti berikut.

val text: String? = null

text?.length

Dengan safe call, kompiler akan melewatkan proses jika objek tersebut
bernilai null.

Apakah Anda pernah mendengar penyanyi bernama Elvis Presley? Ya,


beliau memiliki karakteristik yang dikenal dengan rambut jambulnya
dan mirip dengan tanda operator ini. Tanda tanya menandakan
rambutnya dan titik dua sebagai matanya. Seperti inilah ilustrasinya.

Elvis operator memungkinkan kita untuk menetapkan default


value atau nilai dasar jika objek bernilai null.

val text: String? = null

val textLength = text?.length ?: 7


Kode di atas sebenarnya sama seperti ketika kita
menggunakan if/else berikut.
val textLength = if (text != null) text.length else 7

Elvis akan mengembalikan nilai text.length jika text tidak


bernilai null. Sebaliknya, jika text bernilai null, default value yang akan
dikembalikan.

Sebelum lanjut ke submodul selanjutnya terdapat satu hal yang perlu


diperhatikan dalam penanganan objek nullable. Perhatikan
penggunaan operator non-null assertion (!!), misalnya seperti berikut.

val text: String? = null

val textLength = text!!.length // ready to go ???

Dengan menggunakan non-null assertion kompiler akan mengizinkan


kita untuk mengakses atau mengelola nilai dari sebuah objek nullable.
Namun, penggunaan operator tersebut sangat tidak disarankan karena
akan memaksa sebuah objek menjadi non-null. Sehingga, ketika objek
tersebut bernilai null, Anda tetap akan berjumpa
dengan NullPointerException.

Functions
Function atau fungsi merupakan sebuah prosedur yang memiliki
keterkaitan dengan pesan dan objek. Ketika kita memanggil sebuah
fungsi maka sebuah mini-program akan dijalankan. Fungsi sendiri bisa
diartikan sebagai cara sederhana untuk mengatur program buatan
kita.

Sebuah fungsi dapat kita gunakan untuk mengembalikan nilai.


Pemanggilan sebuah fungsi sendiri, bisa diberi argumen atau tidak.
Pada sub-modul ini kita akan belajar bagaimana membuat sebuah
fungsi pada Kotlin dan mencoba beberapa poin di atas.

fun functionName(param1: Type1, param2: Type2, ...): ReturnType {

return result

}
Pendeklarasian fungsi pada Kotlin diawali dengan kata
kunci fun kemudian dilanjutkan dengan nama fungsi yang dikehendaki.
Selanjutnya adalah parameter yang berada pada fungsi yang
dideklarasikan. Awali dengan nama parameter dan ikuti dengan tipe
parameter itu sendiri yang dipisahkan oleh karakter colon (:). Setiap
parameter yang berada pada sebuah fungsi dipisahkan oleh karakter
koma dan berada di dalam tanda kurung.

fun setUser(name: String, age: Int)

Setelah menentukan nama dan parameter, selanjutnya adalah


menentukan tipe kembalian dari fungsi yang dibuat. Perlu diketahui
fungsi pada Kotlin selalu mengembalikan nilai. Tipe kembalian adalah
nilai yang akan dikembalikan ketika fungsi tersebut dipanggil.
fun setUser(name: String, age: Int): String

Fungsi di atas akan mengembalikan nilai berupa String. Setelah


menentukan tipe nilai kembalian, barulah kita menentukan function
body di mana di dalamnya terdapat expression atau statement untuk
dijalankan. Function body berada di dalam curly braces ({}) setelah tipe
nilai kembalian.
fun setUser(name: String, age: Int): String {

return "Your name is $name, and you $age years old"

Nilai yang akan dikembalikan diikuti oleh kata kunci return. Jika di
dalam suatu fungsi hanya memiliki satu expression untuk menentukan
nilai kembalian, maka fungsi tersebut bisa diubah menjadi expression
body. Kita hanya perlu menambahkan tanda = dan menuliskannya
seperti berikut:
fun setUser(name: String, age: Int): String = "Your name is $name, and you $age years old"

Dengan expression body, kompiler dapat menentukan tipe kembalian


dari fungsi yang dibuat. Sehingga kita tidak perlu menentukan tipe nilai
kembalian secara eksplisit:
fun setUser(name: String, age: Int) = "Your name is $name, and you $age years old"
Jika kita tidak ingin fungsi yang dibuat mengembalikan nilai, kita bisa
menggunakan Unit sebagai tipe nilai kembaliannya. Contohnya seperti
berikut:

fun printUser(name: String): Unit {

print("Your name is $name")

Ketika menggunakan tipe kembalian Unit, Kotlin memungkinkan kita


untuk menghilangkannya. Kenapa demikian? Kompiler akan
mendeteksinya sebagai tipe kembalian yang redundant:
fun printUser(name: String) {

print("Your name is $name")

Pemanggilan fungsi, bisa dilakukan dengan pendekatan tradisional


seperti berikut:
fun main() {

val user = setUser("Alfian", 19)

println(user)

printUser("Alfian")

/*

output :

Your name is Alfian, and you 19 years old

Your name is Alfian

*/

Anatomi Function
Pada materi sebelumnya, kita sudah belajar tentang function (fungsi).
Mulai dari bagaimana cara kita mendeklarasinya, menentukan apakah
fungsi tersebut dapat mengembalikan nilai, serta melampirkan sebuah
argumen ketika fungsi tersebut digunakan.
Pada sub-modul ini kita akan membahas lebih dalam tentang bagian
apa saja yang terdapat dalam sebuah fungsi. Pada dasarnya sebuah
fungsi memiliki 2 (dua) bagian utama yaitu function
header dan function body.

Function Header

Function header adalah bagian yang merupakan konstruksi dari


sebuah fungsi untuk menentukan perilakunya akan seperti apa. Di
dalam function header terdapat visibility modifier, kata kunci fun, nama,
daftar parameter dan nilai kembalian dari fungsi tersebut.
Visibility Modifier

Visibility modifier atau tingkatan akses merupakan bagian spesifik dari


sebuah bahasa pemrograman yang ditujukan untuk mengatur
bagaimana hak akses dari sebuah kelas, fungsi, properti dan variabel.

Secara default ketika kita membuat sebuah fungsi baru, ia akan


memiliki modifier public. Artinya fungsi tersebut dapat diakses dari
luar kelas. Sedangkan contoh pada ilustrasi di atas adalah sebuah
fungsi yang memiliki modifier private. Maka akses dari fungsi tersebut
terbatas hanya untuk kelas di mana fungsi tersebut dideklarasi.

Terdapat beberapa visibility modifier yang akan kita pelajari bersama


pada sub-modul Object Orientation Programming nanti.

Function Name

Setelah visibility modifier, selanjutnya adalah kata kunci fun . Ini


digunakan untuk menandakan jika baris kode tersebut merupakan
sebuah fungsi yang kemudian diikuti oleh nama dari fungsi tersebut.
Nama dari sebuah fungsi merupakan sebuah identifier yang akan
memudahkan kita untuk menggunakan fungsi tersebut. Perlu
diketahui bahwa kita tidak bisa memberikan nama yang sama untuk
beberapa fungsi.

Untuk penamaan dari sebuah fungsi sendiri menggunakan format


penulisan camelCase. Nama dari fungsi tersebut diawali dengan huruf
kecil dan huruf besar untuk kata berikutnya. Ini merupakan standar
penulisan resmi yang sudah ditentukan.

Function Parameter

Ketika kita mendeklarasikan sebuah fungsi baru, kita bisa atau tanpa
menetapkan parameter tersebut. Parameter adalah data atau nilai
yang disematkan ketika fungsi tersebut dipanggil. Nantinya parameter
akan diproses di dalam fungsi tersebut. Kita bisa melampirkan nilai
konstan atau variabel untuk sebuah fungsi ketika ia dipanggil.

Parameter dari sebuah fungsi terdiri dari nama dan tipe dari
parameter itu sendiri. Ia digunakan untuk menentukan nilai atau
variabel apa yang dapat dilampirkan. Setiap parameter dipisahkan
oleh tanda (,). Catatan: setiap parameter bersifat read-only, sehingga
kita hanya diijinkan untuk menggunakan nilainya untuk diproduksi.

Function return type

Terakhir adalah return type. Setiap fungsi yang kita deklarasi sejatinya
akan selalu mengembalikan dan nilai yang akan dikembalikan bisa kita
gunakan untuk keperluan lain. Misalnya untuk dijadikan sebagai
argumen untuk fungsi lainnya.

Lalu apakah tipe ini harus ditentukan setiap deklarasi sebuah fungsi?
Tentu tidak. Jika kita tidak menentukan return type, secara implisit
fungsi tersebut akan mengembalikan nilai dengan tipe Unit, yaitu
return type yang tidak mengembalikan nilai signifikan.

Function Body

Setelah function header, selanjutnya adalah function body, yang


ditandai dengan curly braces. Di dalamnya kita akan menempatkan
sebuah logika kode baik itu sebuah expression atau statement. Seperti
yang dijelaskan pada sub-modul pengenalan, jika kita menetapkan
sebuah fungsi dapat mengembalikan nilai, maka kita wajib menambah
sebuah baris kode yang diawali dengan kata kunci return yang diikuti
oleh expression untuk menetapkan nilai yang akan dikembalikan.

Sebaliknya, jika kita tidak ingin mengembalikan nilai, kita tidak perlu
menambahkannya seperti yang disebutkan di atas.
Setiap fungsi yang kita deklarasikan, memiliki ruang lingkup tersendiri.
Contohnya saat kita mendeklarasi sebuah variabel di dalamnya,
variabel tersebut akan menjadi variabel lokal untuk fungsi itu sendiri.
Dengan demikian, variabel tersebut tidak dapat diakses dari fungsi
lainnya meskipun berada di dalam satu kelas yang sama.

Named dan Default Argument


Di beberapa kasus pembuatannya, sebuah fungsi bisa menjadi cukup
kompleks dengan banyaknya parameter. Alhasil saat ingin memanggil
fungsi tersebut, kita harus menghafal posisi dari parameter agar tidak
salah dalam melampirkan sebuah argumen.

Named Argument

Untuk mengatasi hal ini Kotlin menawarkan sebuah cara. Dengan ini,
kita tak perlu lagi menghafal posisi dari sebuah parameter. Karena
ketika sebuah fungsi dipanggil, kita bisa menentukan argumen dari
parameter mana yang ingin dilampirkan dengan memanggil nama dari
parameter tersebut. Misalnya kita mempunyai sebuah fungsi seperti
berikut:

fun getFullName(first: String, middle: String, last: String): String {

return "$first $middle $last"

Nah, dengan memanfaatkan named argument, kita bisa


menuliskannya seperti di bawah ini:

fun main() {

val fullName = getFullName(first = "Kotlin" , middle = " is ", last =


"Awesome")

print(fullName)

}
fun getFullName(first: String, middle: String, last: String): String {

return "$first $middle $last"

Menariknya lagi, kita bisa mengubah posisi dari argumen ketika


dilampirkan, misalnya seperti ini:

fun main() {

val fullName = getFullName(middle = " is " , first = "Kotlin", last =


"Awesome")

print(fullName)

fun getFullName(first: String, middle: String, last: String): String {

return "$first $middle $last"

Dengan cara seperti di atas, kita tidak perlu lagi menghafal posisi dari
parameter jika ingin melampirkan sebuah argumen. Cukup hafalkan
nama dari parameter tersebut.

Default Argument

Tidak sampai di situ, Kotlin juga memungkinkan kita untuk


menentukan nilai default dari sebuah parameter. Jika kita melewatkan
argumen untuk dilampirkan, maka nilai default tersebut lah yang akan
digunakan.

Untuk menambahkan nilai default itu sendiri pun cukup mudah, yaitu
dengan cara menempatkannya langsung tepat di samping dari
parameter seperti halnya ketika ingin menginisialisasikan sebuah nilai
untuk variabel. Contohnya seperti berikut:

fun getFullName(

first: String = "Kotlin",

middle: String = " is ",

last: String = "Awesome"): String {

return "$first $middle $last"

Kita bisa memanggil fungsi di atas seperti biasanya. Tetapi karena


parameternya sudah memiliki nilai, maka argumen untuk fungsi
tersebut bisa dilewatkan ketika dipanggil.

fun main() {

val fullName = getFullName()

print(fullName)

/*

output : Kotlin is Awesome

*/

Menarik bukan? Ketika kita telah menetapkan nilai default, kita tak
perlu khawatir saat lupa melampirkan sebuah argumen. Tentunya ini
menghindari kita dari eror. Meskipun begitu, kita tetap bisa
melampirkan sebuah argumen. Contohnya seperti berikut:

fun main() {
val fullName = getFullName(first = "Dicoding")

print(fullName)

/*

output : Dicoding is Awesome

*/

Dengan memanfaatkan named dan default argument, kode yang kita


tulis lebih mudah dibaca. Ini pun dapat membantu kita dalam
menggunakan fungsi yang cukup kompleks.

Vararg (Variable Argument)


Selain named dan default argument, Kotlin juga memiliki vararg
(variable argument). Dengan menggunakan kata kunci vararg, kita
juga bisa menyederhanakan beberapa parameter yang memiliki tipe
data yang sama menjadi parameter tunggal.

Dengan vararg sebuah fungsi dapat memiliki jumlah parameter


berdasarkan jumlah argumen yang kita masukkan ketika fungsi
tersebut dipanggil. Contoh dari penggunaan vararg adalah sebagai
berikut.

fun sumNumbers(vararg number: Int): Int {

return number.sum()

Bisa kita perhatikan pada contoh kode di atas bahwa kata


kunci vararg ditempatkan sebelum nama parameter. Ketika ingin
memanggil fungsi tersebut, kita bisa melampirkan beberapa argumen
seperti berikut.

fun main() {
val number = sumNumbers(10, 20, 30, 40)

print(number)

/*

output : 100

*/

Karena pada dasarnya adalah sebuah Array, kita bisa memanggil


fungsi atau properti yang tersedia pada kelas Array dari dalam fungsi
tersebut, contohnya seperti properti size.

fun main() {

val number = getNumberSize(10, 20, 30, 40, 50)

print(number)

fun getNumberSize(vararg number: Int): Int {

return number.size

/*

output : 5

*/
Lalu, kapan kita membutuhkan vararg? Ketika sebuah fungsi yang
menggunakannya tidak mengetahui jumlah argumen yang akan
disematkan ketika fungsi tersebut dipanggil. Contoh penerapan bisa
kita liat pada fungsi String.format(), di mana fungsi tersebut terdapat
parameter yang ditandai dengan vararg dan dapat disematkan
beberapa argumen tanpa harus tahu batasannya.

Aturan pada Vararg Arguments

Dalam penggunaannya, terdapat aturan yang perlu kita ketahui.


Pertama, di dalam sebuah fungsi, tidak diizinkan untuk memiliki 2
(dua) parameter bertanda vararg.

fun sumNumbers(vararg number: Int, vararg number2: Int)

Ketika kode di atas dijalankan, proses kompilasi akan gagal dengan log
eror sebagai berikut:
Kotlin: Multiple vararg-parameters are prohibited

Selanjutnya, jika kita ingin menambahkan parameter baru tanpa kata


kunci vararg, parameter yang ditandai dengan vararg sebaiknya
berada pada posisi terakhir. Contohnya seperti berikut.

fun main() {

sets("Kotlin", 10, 10)

fun sets(name: String, vararg number: Int): Int {

...

Lalu, bagaimana jika kita ingin menempatkan parameter yang


ditandai vararg pada posisi pertama? Kita bisa mendefinisikannya
secara langsung. Namun, berbeda saat fungsi tersebut dipanggil di
mana kita harus menggunakan named argument saat ingin
melampirkan argumen untuk parameter yang tidak ditandai
dengan vararg. Contohnya seperti berikut.

fun main() {

sets(10, 10, name = "Kotlin")

fun sets(vararg number: Int, name: String): Int {

...

Kenapa demikian? Saat kita tidak menandai argumen tersebut untuk


parameter yang mana, kompiler akan menetapkan jika argumen
tersebut untuk parameter yang ditandai dengan vararg.

Vararg vs Array

Karena semua argumen ditampung di dalam sebuah Array, akan


muncul pertanyaan, "Apa bedanya ketika kita
menggunakan Array sebagai tipe parameter?" Misal seperti berikut:

fun sets(number: Array<Int>) {

...

Dari sini kita bisa lihat langsung letak perbedaannya di mana. Ketika
fungsi di atas dipanggil, fungsi tersebut membutuhkan argumen
berupa nilai yang sudah berbentuk Array seperti berikut:

fun main() {

val number = arrayOf(10, 20, 30, 40)


sets(number)

fun sets(number: Array<Int>) {

...

Berbeda ketika kita menggunakan vararg, kita bisa memasukkan


argumen satu persatu. Lalu apakah bisa kita memasukkan nilai yang
sudah berbentuk Array sebagai argumen untuk parameter yang
ditandai dengan vararg?

Tentu bisa! Dengan memanfaatkan spread operator (*) seperti berikut.

fun main() {

val number = intArrayOf(10, 20, 30, 40)

sets(10, 20, 20, *number , 10)

fun sets(vararg number: Int): Int {

...

Dalam penggunaannya, spread operator ditempatkan sebelum nama


variabel yang ingin dilampirkan.

Rangkuman dari Kotlin Fundamental


Sebelum Anda lanjut ke modul berikutnya, berikut adalah beberapa
rangkuman dari materi yang sudah dipelajari di modul ini.
 Sama seperti bahasa pemrograman lain, Kotlin memiliki fungsi
untuk mencetak nilai pada console, yaitu
fungsi print() dan println().
 Untuk mendeklarasi variable, Anda akan menggunakan kata
kunci var atau val. var atau val digunakan untuk mengontrol nilai
dari sebuah variabel. Dengan kata kunci var kita bisa mengubah
nilai yang sudah kita inisialisasikan.
 Untuk membuat variable yang menampung data berupa text,
Anda dapat menggunakan tipe data Char untuk menyimpan satu
karakter dan tipe data String untuk menyimpan beberapa
karakter.
 Lalu, untuk menampung data berupa number, Anda akan
menggunakan beberapa tipe data di bawah ini.
o Int (32 Bit)
Int adalah tipe data yang umumnya digunakan untuk
menyimpan nilai numerik. Int dapat menyimpan data dari
range -231 sampai +231-1. Dengan ukuran 32 Bit, kita bisa
menggunakannya untuk menyimpan nilai yang besar.
Catatannya, tetap lihatlah batasan nilai maksimal yang
dapat dimasukkan.
o Long (64 Bit)
Long adalah tipe data yang digunakan untuk menyimpan
nilai numerik yang lebih besar yaitu dari range -2 63 sampai
+263-1.
o Short (16 Bit)
Short merupakan sebuah bilangan bulat yang hanya dapat
menyimpan nilai yang kecil karena hanya berukuran 16 Bit.
o Byte (8 Bit)
Dengan ukuran yang kecil, Byte hanya mampu menyimpan
nilai yang kecil sama halnya seperti Short. Byte biasa
digunakan untuk keperluan proses membaca dan menulis
data dari sebuah stream file atau jaringan.
o Double (64 Bit)
Sama halnya dengan Long yang memiliki ukuran yang
besar, Double mampu menyimpan nilai numerik yang
besar pula. Pada umumnya, Double digunakan untuk
menyimpan nilai numerik pecahan.
o Float (32 Bit)
Float memiliki ukuran yang lebih kecil, yakni hanya sampai
6-7 angka di belakang koma.
 Selanjutnya adalah Array, yakni tipe data yang memungkinkan
Anda untuk menyimpan beberapa objek di dalam satu variabel.
 Kotlin juga memungkinkan Anda untuk membuat Array dengan
tipe data primitif dengan memanfaatkan beberapa fungsi spesifik
seperti berikut.
o intArrayOf() : IntArray
o booleanArrayOf() : BooleanArray
o charArrayOf() : CharArray
o longArrayOf() : LongArray
o shortArrayOf() : ShortArray
o byteArrayOf() : ByteArray
 Kotlin mendukung juga tipe data Boolean di mana tipe data yang
hanya memiliki dua nilai, yaitu true dan false. Selain itu, terdapat
3 (tiga) operator yang dapat digunakan pada Boolean.
o Conjunction atau AND (&&)
Operator AND (&&) akan mengembalikan nilai true jika
semua hasil evaluasi expression yang diberikan bernilai
true.
o Disjunction atau OR (||)
Berbeda dengan operator AND (&&), operator OR (||) akan
mengembalikan nilai true jika hasil evaluasi dari salah satu
expressions yang diberikan bernilai true.
o Negation atau NOT (!)
Berbeda dengan operator AND (&&) dan operator OR(||),
operator NOT(!) digunakan untuk melakukan negasi pada
hasil evaluasi expression yang diberikan.
 Jika ingin menginisialisasi nilai dari sebuah variabel berdasarkan
suatu kondisi, gunakan If Expression.
 Dengan Kotlin kita mudah dalam mengelola variable nullable
sehingga dapat meminimalisasi
terjadinya NullPointerException dengan menggunakan Safe
Call dan Elvis Operator.

 Function atau fungsi merupakan sebuah prosedur yang


memiliki keterkaitan dengan pesan dan objek. Ketika kita
memanggil sebuah fungsi, sebuah mini-program akan dijalankan.
Fungsi sendiri bisa diartikan sebagai cara sederhana untuk
mengatur program buatan kita.

 Anatomi dari sebuah function terdiri dari 2 (dua) bagian utama,


yaitu function header dan function body:
o Function Header
Function header adalah bagian yang merupakan konstruksi
dari sebuah fungsi untuk menentukan perilakunya akan
seperti apa. Di dalam function header terdapat visibility
modifier, kata kunci fun, nama, daftar parameter dan nilai
kembalian dari fungsi tersebut.
o Function Body
Function Body adalah bagian yang dalamnya kita akan
menempatkan sebuah logika kode baik itu sebuah
expression atau statement.
 Named argument berguna untuk menyebutkan nama
parameter saat memanggil fungsi, sehingga Anda dapat
memanggil fungsi dengan urutan argumen yang berbeda.
 Default argument berguna untuk memberikan nilai default
pada parameter fungsi, sehingga Anda tidak perlu selalu
memberikan nilai saat memanggil fungsi tersebut.

 varargs dapat digunakan untuk menyederhanakan deklarasi


beberapa parameter yang memiliki tipe yang sama.
Kita sudah selesai dengan Kotlin Fundamental di mana Anda sudah
mempelajari tentang cara menampilkan pesan pada konsol, berbagai
macam tipe data, nullable type, dan cara membuat Fungsi di Kotlin.
Selanjutnya, kita akan mempelajari materi Control Flow. Tetap
semangat, ya!

fun main() {
val officeOpen = 7
val now = 10
val isOpen = now > officeOpen

if (!isOpen) {
print("Office is closed")
} else {
print("Office is open")
}
}

Outputnya adalah

Fungsi yang digunakan untuk mencetak teks ke dalam layar atau konsol dan
menambahkan baris baru adalah ...
println()
system.out.cetak()
print()
printNewLine()

Misalnya Anda memiliki fungsi seperti berikut.


fun getFullAddress(streetName: String = "Jl. Malioboro", number: Int = 50): String
{
return "I live in $streetName No. $number"
}

Manakah cara yang tidak menghasilkan error dalam memanggil fungsi tersebut?
getFullAddress()
getFullAddress(streetName = "Jl. Margonda")
getFullAddress(streetName = "Jl. Margonda" , number = 50)

Semuanya tidak menghasilkan error

Berikut merupakan cara penulisan komentar pada bahasa pemrograman Kotlin,


kecuali ...
//
/* … */
/- … -/
// dan /* … */

Komponen Control Flow


Kita telah belajar mengenai If Expression pada sub-modul
sebelumnya. If Expression merupakan salah satu bagian dari Control
Flow. Pada sub-modul ini kita akan mempelajari tentang apa itu
control flow dan juga beberapa bagian lain yang ada di dalamnya.

Apa itu Control Flow?

Ketika kita mengembangkan sebuah program, tentu kita harus tahu


seperti apa alurnya. Control flow adalah cara kita mengontrol alur dari
sebuah program berdasarkan kondisi saat program tersebut berjalan.

Terdapat beberapa bagian dari control flow yang akan kita pelajari,
antara lain:

 When Expression
 Expression & Statement
 While and Do While
 Range and For Loop
 Break and Continue Labels

Kita akan mempelajari seperti apa dan bagaimana cara menerapkan


beberapa control flow di atas.
Expressions dan Statements
Ketika mempelajari sebuah bahasa pemrograman, kita selalu
dihadapkan dengan istilah expressions dan statement. Ini adalah 2 (dua)
istilah yang kadang disalahpahami.

Untuk lebih mudah memahaminya, marilah kita lihat contoh


kode If sebagai statement berikut.
if (now > openOffice) {

print("Office already open")

} else {

print("Office close")

Pada contoh kode di atas, if dikatakan sebagai statement karena ia


tidak mengembalikan nilai apapun, hanya sebagai percabangan pada
bahasa Kotlin.

Namun, yang menarik If pada bahasa Kotlin juga bisa digunakan


sebagai expression. Yang dimaksud dengan expression adalah
statement yang dapat mengembalikan nilai dan bisa kita simpan ke
dalam sebuah variabel seperti contoh berikut.
val office = if (now > openOffice) "Office already open" else "Office close"
print(office)

Pada kode di atas, If akan mengembalikan nilai kedalam variabel office.


Apabila kondisi pada if terpenuhi, variabel office akan berisi "Office
already open". Namun ketika kondisinya tidak terpenuhi, ia akan berisi
"Office close".

Jadi, sudah paham kan perbedaan antara statement dan expression?

Nah, perlu Anda ketahui bahwa di dalam sebuah expression juga bisa
terdapat sebuah expression lagi. Contohnya seperti berikut.

fun main() {
sum(1 , 1 * 4)
}

fun sum(value1: Int, value2: Int) = value1 + value2

Pada kode diatas 1 * 4 merupakan sebuah expression yang ada pada


pemanggilan fungsi sum() alias fungsi yang mengembalikan nilai.
Setiap fungsi selalu mengembalikan nilai. Alhasil, pemanggilan sebuah
fungsi merupakan sebuah expression.

Contoh lain dari statement adalah inisialisasi sebuah variabel seperti


berikut.

fun main() {
val value1 = 10
val value2 = 10

sum(value1, value2)
}

fun sum(value1: Int, value2: Int) = value1 + value2


Pada kode di atas, deklarasi variabel value1 dan value2 merupakan
sebuah statement, sedangkan pemanggilan fungsi sum merupakan
sebuah expression.

When Expressions
Untuk menentukan statement atau expression kita menggunakan If
Expression. Selain itu kita juga bisa gunakan When Expression,
yakni mekanisme yang memungkinkan nilai dari sebuah
variabel/expression, mampu mengubah alur program.

Contoh sederhana dalam penggunaan when expression adalah seperti


berikut:

val value = 7

when(value){

6 -> println("value is 6")


7 -> println("value is 7")

8 -> println("value is 8")

/*

output: value is 7

*/

when akan mencocokan semua argumen yang berada di


setiap branch secara berurutan sampai salah satu kondisi terpenuhi. Di
dalam when kita juga bisa menambahkan branch else seperti berikut:

val value = 20

when(value){

6 -> println("value is 6")

7 -> println("value is 7")

8 -> println("value is 8")

else -> println("value cannot be reached")

/*

output: value cannot be reached


*/

else akan dievaluasi jika tiada satupun kondisi yang terpenuhi


pada branch sebelumnya. Sama halnya seperti if expression, when
expression dapat mengembalikan nilai dan dapat disimpan di dalam
sebuah variabel seperti berikut:

val value = 7

val stringOfValue = when (value) {

6 -> "value is 6"

7 -> "value is 7"

8 -> "value is 8"

else -> "value cannot be reached"

println(stringOfValue)

/*

output : value is 7

*/

else adalah hal wajib jika kita menggunakan when expression untuk
mengembalikan nilai. Bagaimana jika kita melewatkannya? Akan tampil
eror berikut:
'when' expression must be exhaustive, add necessary 'else'
branch
Jika kita memiliki dua atau lebih baris kode yang akan kita jalankan di
setiap branch, kita bisa memindahkannya ke dalam curly braces seperti
berikut:

val value = 7

val stringOfValue = when (value) {

6 -> {

println("Six")

"value is 6"

7 -> {

println("Seven")

"value is 7"

8 -> {

println("Eight")

"value is 8"

else -> {

println("undefined")

"value cannot be reached"

}
println(stringOfValue)

/*

output :

Seven

value is 7

*/

when juga memungkinkan kita untuk memeriksa instance dengan tipe


tertentu dari sebuah objek menggunakan is atau !is. Contohnya seperti
berikut:

val anyType : Any = 100L

when(anyType){

is Long -> println("the value has a Long type")

is String -> println("the value has a String type")

else -> println("undefined")

/*

output : the value has a Long type

*/

Selain itu, when expression juga bisa kita gunakan untuk memeriksa
nilai yang terdapat pada sebuah Range atau Collection. Range sendiri
merupakan salah satu tipe data yang unik di mana kita dapat
menentukan nilai awal dan nilai akhir. Range dan Collection akan
dibahas terpisah pada sub-modul berikutnya.

Berikut adalah contoh saat kita hendak mengecek apakah sebuah nilai
ada di dalam sebuah Range atau tidak.

val value = 27

val ranges = 10..50

when(value){

in ranges -> println("value is in the range")

!in ranges -> println("value is outside the range")

/*

output : value is in the range

*/

Branch pertama pada contoh kode di atas akan memeriksa apakah


nilai dari value terdapat di cakupan nilai ranges. Sedangkan
untuk branch kedua akan memeriksa apakah nilai dari value tidak
terdapat pada nilai yang dicakup oleh ranges.

Sejak Kotlin 1.3, kita dapat menangkap subjek dari when expression di
dalam sebuah variabel. Contohnya seperti berikut:

fun main() {

val registerNumber = when(val regis = getRegisterNumber()){


in 1..50 -> 50 * regis

in 51..100 -> 100 * regis

else -> regis

fun getRegisterNumber() = Random.nextInt(100)

Perhatikan. Cakupan variabel yang dapat ditangkap, terbatas di


dalam body when expression.

Jika kita melihat penjelasan dan contoh penggunaan dari when


expression di atas, ia memiliki kesamaan dengan if expression.
Lantas disituasi seperti apa kita menggunakannya? if
expression sebaiknya digunakan ketika kondisi yang diberikan tidak
lebih dari 2 (dua) dan kondisi yang diberikan tidak terlalu rumit.

val anyType : Any = 100L

if (anyType is Long){

println("the value has a Long type")

} else {

println("the value is not Long type")

Berbeda dengan when expression, ia bisa digunakan ketika kondisi


yang diberikan lebih dari 2 (dua).

val anyType: Any = 100L

when (anyType) {
is Long -> println("the value has a Long type")

is Int -> println("the value has a Int type")

is Double -> println("the value has a Double type")

else -> println("undefined")

While dan Do While


Bayangkan ketika kita ditugaskan untuk mencetak beberapa baris teks
yang sama ke dalam konsol seperti berikut:

Hello World

Hello World

Hello World

Hello World

Hello World

Kita pasti langsung terpikir akan menulis programnya seperti berikut:

fun main() {

println("Hello World")

println("Hello World")

println("Hello World")

println("Hello World")

println("Hello World")

}
Think! Bagaimana jika teks yang harus ditampilkan berjumlah banyak?
Tentu kita tidak mungkin menuliskan fungsi println() sesuai dengan
jumlah yang kita ingin tampilkan.

Nah, untuk mengatasinya kita bisa menggunakan perulangan.


Perulangan adalah proses perulangan blok yang sama tanpa henti
sampai kondisi yang diberikan tidak terpenuhi atau bernilai false.

Perulangan terdiri dari While, Do While dan For Loop. Sub-modul ini
akan membahas While dan Do While. Sementara For Loop akan
dibahas terpisah pada sub-modul berikutnya.

While

Untuk menggunakan While, kita membutuhkan kata kunci while, lanjut


ke kondisi di dalam tanda kurung, dan diakhiri oleh
blok body dari while itu sendiri. Berikut adalah contoh dari penggunaan
While:

fun main() {

var counter = 1

while (counter <= 7){

println("Hello, World!")

counter++

/*

output :

Hello, World!

Hello, World!
Hello, World!

Hello, World!

Hello, World!

Hello, World!

Hello, World!

*/

Perhatikan kondisi dari While di atas, selama nilai dari variabel counter
kurang dari sama dengan 7 maka kode yang di dalamnya akan terus
dilakukan. Lalu ketika kondisi tersebut sudah tak terpenuhi maka
proses perulangan akan dihentikan.

While bersifat Entry Controlled Loop. Artinya, kondisi yang diberikan


akan dievaluasi terlebih dahulu. Jika kondisi tersebut terpenuhi maka
proses perulangan akan dijalankan.

Jika kondisi yang diberikan tidak terpenuhi sejak awal maka proses
perulangan tidak akan dijalankan. Untuk mengujinya Anda bisa
menulis dan menjalankan kode berikut:

fun main() {

var counter = 8

while (counter <= 7){

println("Hello, World!")

counter++

}
Dengan While kita tidak perlu menuliskan fungsi println() secara
berulang untuk mencetak teks ke dalam konsol seperti contoh kasus di
awal.

Do While

Selain menggunakan While, kita juga bisa menggunakan Do While


untuk melakukan perulangan seperti berikut:

fun main() {

var counter = 1

do {

println("Hello, World!")

counter++

} while (counter <= 7)

/*

output:

Hello, World!

Hello, World!

Hello, World!

Hello, World!

Hello, World!

Hello, World!

Hello, World!
*/

Berbeda dengan While, Do While bersifat Exit Controlled Loop di


mana proses perulangan akan langsung dijalankan di awal. Jika telah
selesai, barulah kondisi yang diberikan akan dievaluasi.

Saat menggunakan While dan Do While perhatikan infinite loop, yaitu


kondisi di mana proses perulangan berlangsung terus menerus sampai
aplikasi menjadi crash. Contoh dari infinite loop adalah seperti berikut:

fun main() {

var value = 'A'

do {

print(value)

} while (value <= 'Z')

Infinite loop terjadi jika kondisi yang diberikan selamanya terpenuhi


atau bernilai true.

While dan Do While sendiri tidak dapat digunakan untuk melakukan


perulangan pada rentan angka. Untuk melakukannya kita bisa
menggunakan For Loop yang akan kita pelajari pada sub-modul
selanjutnya.

Range
Seperti yang disampaikan sebelumnya, Range merupakan salah satu
tipe yang unik pada kotlin. Kita dapat menentukan nilai awal dan nilai
akhir pada Range. Range direpresentasikan dengan operator .. atau
dengan fungsi rangeTo() dan downTo().

Terdapat beberapa cara untuk membuat Range di Kotlin. Pertama,


seperti berikut:
val rangeInt = 1..10

Kode diatas menggunakan operator .. untuk membuat Range.


Variabel rangeInt di atas mencakup nilai 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. Jarak
antara dua nilai yang dicakup, ditentukan oleh step. Secara default,
step bernilai 1. Untuk mendapatkan step kita bisa menggunakan
properti step seperti contoh berikut:

fun main() {

val rangeInt = 1..10

print(rangeInt.step)

/*

output: 1

*/

Dan untuk mengubah nilai dari step bisa dilakukan ketika kita
menginisialisasi nilai yang dicakup Range itu sendiri:

fun main() {

val rangeInt = 1..10 step 2

rangeInt.forEach {

print("$it ")

println(rangeInt.step)

}
/*

output: 1 3 5 7 9 2

*/

Pada kode di atas kita menentukan nilai step adalah 2, maka nilai yang
dicakup variabel rangeInt adalah 1, 3, 5, 7, 9.

Selanjutnya adalah menggunakan fungsi rangeTo():

val rangeInt = 1.rangeTo(10)

Kode di atas, operator .. digantikan dengan fungsi rangeTo() untuk


membuat Range . Nilai yang dicakup pada kode di atas sama seperti
kode sebelumnya ketika menggunakan operator ...

Kita juga bisa menentukan nilai yang dicakup pada Range dengan
urutan terbalik seperti berikut:

val downInt = 10.downTo(1)

Kode di atas menggunakan fungsi downTo() untuk menentukan nilai


dengan urutan terbalik. Variabel downInt di atas mencakup nilai 10, 9,
8, 7, 6, 5, 4, 3, 2, 1.

Kita juga bisa memeriksa apakah suatu nilai ada pada cakupan nilai
Range.

fun main() {

val tenToOne = 10.downTo(1)

if (7 in tenToOne) {

println("Value 7 available")

}
/*

output: Value 7 available

*/

Pada kode di atas kita menggunakan kata kunci in untuk memeriksa


apakah 7 berada diantara kisaran 1 sampai 10. Expression yang
dievaluasi pada if di atas sama seperti ketika
menggunakan expression berikut:

fun main() {

if (1 <= 7 && 7 <= 10){

println("Value 7 available")

/*

output: Value 7 available

*/

Nah, di atas kita telah memeriksa apakah suatu nilai ada pada nilai
cakupan Range. Sebaliknya, kita juga bisa memeriksa apakah suatu
nilai tidak ada pada nilai cakupan Range tersebut. Kita bisa
menggunakan kata kunci !in seperti ini:

fun main() {

val tenToOne = 10.downTo(1)

if (11 !in tenToOne) {

println("No value 11 in Range ")

}
}

/*

output: No value 11 in Range

*/

Range pada Kotlin mendukung beberapa tipe integral


seperti IntRange, LongRange dan CharRange. Sehingga selain nilai
numerik, kita juga bisa menentukan tipe Character sebagai nilai yang
dicakup oleh Range:

val rangeChar = 'A'.rangeTo('F')

Nilai pada variable rangeChar di atas mencakup A, B, C, D, E, F

Sebagai referensi lebih lanjut mengenai beberapa konsep Kotlin yang


sudah dipelajari, Anda dapat melihat video berikut.

 Kotlin under the hood: Understand the internals (Google I/O'19)

For Loop

Sama seperti While dan Do While, For merupakan konsep perulangan


pada blok yang sama selama hasil evaluasi kondisi yang diberikan
terpenuhi atau bernilai true. For dapat digunakan
pada Ranges, Collections, Arrays dan apa pun yang
menyediakan iterator. Contoh dari For loop sendiri adalah sebagai
berikut.

fun main() {

val ranges = 1..5

for (i in ranges){

println("value is $i!")

}
}

/*

output :

value is 1!

value is 2!

value is 3!

value is 4!

value is 5!

*/

Kode di atas merupakan contoh ketika melakukan perulangan pada


Ranges dengan menggunakan range expression yang sudah kita
pelajari sebelumnya. Karena menggunakan range expression, kita juga
dapat menuliskannya seperti berikut.

fun main() {

val ranges = 1.rangeTo(5)

for (i in ranges){

println("value is $i!")

/*

output :
value is 1!

value is 2!

value is 3!

value is 4!

value is 5!

*/

Selain itu, kita juga dapat menuliskan For loop menggunakan range
expression seperti berikut.

fun main() {

val ranges = 1.rangeTo(10) step 3

for (i in ranges ){

println("value is $i!")

/*

output :

value is 1!

value is 4!

value is 7!

value is 10!

*/
Pada kode di atas, kita menambahkan ekstensi step yang akan
mengembalikan nilai baru dengan tipe IntProgression dengan jarak
nilai sebelumnya adalah 3.

Kita juga dapat mengakses indeks untuk setiap elemen yang ada
pada ranges dengan memanfaatkan fungsi withIndex() seperti berikut.

fun main() {

val ranges = 1.rangeTo(10) step 3

for ((index, value) in ranges.withIndex()) {

println("value $value with index $index")

/*

output :

value 1 with index 0

value 4 with index 1

value 7 with index 2

value 10 with index 3

*/

Kita menggunakan kata kunci for untuk memulai proses perulangan.


Untuk tujuan yang sama, kita juga bisa memanfaatkan salah satu
ekstensi pada Kotlin yaitu forEach. Contohnya seperti berikut.

fun main() {

val ranges = 1.rangeTo(10) step 3

ranges.forEach { value ->


println("value is $value!")

/*

output :

value is 1!

value is 4!

value is 7!

value is 10!

*/

Dengan menggunakan forEach , kita tidak perlu lagi menggunakan for


secara terpisah seperti sebelumnya. Ia akan otomatis melakukan
perulangan pada setiap item dari variabel tersebut sampai akhir.
Untuk mendapatkan nilainya, kita definisikan variabel value seperti
contoh di atas.

Catatan:
Kode ini merupakan contoh dari penerapan Lambda Expression. Jika
Anda merasa asing dengan penulisan kode tersebut, tenang saja, kita
akan mempelajarinya pada modul-modul selanjutnya. Untuk sekarang,
cukup gunakan saja terlebih dahulu.

Break dan Continue


Ketika melakukan perulangan, terkadang kita dihadapkan dengan data
yang tak sesuai harapan. Contoh, seperti berikut:

fun main() {

val listOfInt = listOf(1, 2, 3, null, 5, null, 7)


for (i in listOfInt) {

print(i)

/*

output: 123null5null7

*/

Proses perulangan pada kode di atas akan menghasilkan nilai null. Jika
kita mengelola nilai tersebut, ada potensi NullPointerException di
sana. Lalu bagaimana kita melewatkan atau menghentikan proses
perulangan jika nilai yang dihasilkan bernilai null? Nah, di sini kita bisa
menggunakan Break dan Continue.

Continue digunakan untuk melewatkan proses iterasi dan lanjut


dengan proses iterasi berikutnya. Sementara itu, Break digunakan
untuk menghentikan proses iterasi.

Berikut adalah contoh proses iterasi pada kode di atas. Kita akan coba
melewatkannya jika nilai yang dihasilkan adalah null.

fun main() {

val listOfInt = listOf(1, 2, 3, null, 5, null, 7)

for (i in listOfInt) {

if (i == null) continue

print(i)

}
/*

output: 12357

*/

Pada kode di atas kita menggunakan kata kunci continue. Jika hasil
evaluasi expression yang diberikan bernilai true, maka proses iterasi
akan dilewatkan dan lanjut ke proses iterasi berikutnya.

Berikut adalah contoh jika kita ingin menghentikan proses iterasi


ketika nilai yang dihasilkan bernilai null.

fun main() {

val listOfInt = listOf(1, 2, 3, null, 5, null, 7)

for (i in listOfInt) {

if (i == null) break

print(i)

Penggunaan break pada kode di atas akan langsung menghentikan proses iterasi jika
variabel i bernilai null.

Break dan Continue Labels

Pada Kotlin, sebuah expression dapat ditandai dengan sebuah label.


Label pada Kotlin memiliki sebuah identifier yang diikuti dengan
tanda @. Contoh dari sebuah label adalah foo@ atau bar@.

Untuk melabeli sebuah expression, kita cukup menempatkan label di


depannya. Contohnya seperti berikut:

fun main() {
loop@ for (i in 1..10) {

println("Outside Loop")

for (j in 1..10) {

println("Inside Loop")

if ( j > 5) break@loop

/*

output :

Outside Loop

Inside Loop

Inside Loop

Inside Loop

Inside Loop

Inside Loop

Inside Loop

*/

Pada kode diatas, break yang sudah ditandai dengan label akan
dilompati ke titik awal proses perulangan yang sudah ditandai dengan
label. break akan menghentikan proses perulangan terluar dari dalam
proses perulangan, di mana break tersebut dipanggil.

Rangkuman dari Control Flow


Sudah bisa menentukan alur program yang akan dikembangkan? Yuk
kita ulas lagi apa yang sudah kita pelajari pada sub-modul Control
Flow:

 Jika memiliki beberapa ekspresi untuk menentukan hasil


evaluasi, Anda bisa menggunakan when expression. Karena
sebuah expression, when dapat mengembalikan nilai yang dapat
ditampung pada sebuah variabel.
 Sama seperti when, if expression dapat mengembalikkan nilai
yang dapat ditampung pada sebuah variabel. Namun sedikit
berbeda dengan when, if lebih cocok digunakan jika ekspresi
yang akan digunakan untuk dievaluasi hanya 1 (satu).
 Dalam mempelajari bahasa pemgrograman, Anda akan sering
menjumpai istilah expressions dan statement.
 Jika ingin melakukan perulangan, ada beberapa cara yang dapat
diterapkan yaitu:

o While
While bersifat Entry Controlled Loop. Artinya, kondisi yang
diberikan akan dievaluasi terlebih dahulu. Jika kondisi
tersebut terpenuhi maka proses perulangan akan
dijalankan.
o Do While
Do While bersifat Exit Controlled Loop di mana proses
perulangan akan langsung dijalankan di awal. Jika telah
selesai, barulah kondisi yang diberikan akan dievaluasi.
o For Loop
For merupakan konsep perulangan pada blok yang sama
selama hasil evaluasi kondisi yang diberikan terpenuhi atau
bernilai true. For memanfaatkan tipe data Range untuk
menentukan kondisi yang akan dievaluasi.
 Saat menggunakan While dan Do While perhatikan infinite loop,
yaitu kondisi di mana proses perulangan berlangsung terus
menerus sampai aplikasi menjadi crash.
 Saat menerapkan perulangan, kita bisa memanfaatkan kata
kunci break dan continue. Kedua kata kunci tersebut digunakan
untuk menentukan proses perulangan akan seperti apa di mana
break digunakan untuk menghentikan proses perulangan
walaupun hasil evaluasi masih menghasil true dan continue
digunakan untuk melanjutkan proses perulangan selanjutnya.

Apa output dari program berikut?


for (i in 1..3) {
for (j in 1..i) {
print(j)
}
}

112123
123
123123123
jjjjjj

Apakah keyword yang digunakan untuk menghentikan proses iterasi?


this
break
continue
return

Statement manakah yang salah jika dimasukkan ke dalam when expression


berikut?
var a = 10

when (a) {
// ...
}

in 1..22 -> print("Ok")


11, 12 -> print("Ok")
> 0 -> print("Ok")
a + a -> print("Ok")

Bagaimanakah cara membuat range dari a hingga b yang tepat?


a, b
a_b
ab
a..b

Apakah yang Anda ketahui tentang infinite loop?


Kondisi di mana proses perulangan berlangsung terus menerus hingga aplikasi
crash.
Proses perulangan yang akan langsung dijalankan di awal.
Langkah untuk menghentikan proses iterasi.
Melewatkan proses iterasi kemudian lanjut ke proses iterasi berikutnya.

fun main() {
var counter = 3
do {
print("Hi Kotlin! ")
counter++
} while (counter < 3)
}

Apakah output jika kode di atas dijalankan?


Infinite Loop
Hi Kotlin! Hi Kotlin! Hi Kotlin!
Tidak ada output
Hi Kotlin!

Jika Anda memiliki kode seperti berikut:


for (i in 10.rangeTo(11)) {
print("$i ")
}

Maka outputnya adalah …


10 11 12
10 11
11 12
Semua salah
Object-Oriented Programming

Pada sub-modul awal, kita sudah mengetahui bahwa Kotlin memberi


dukungan luas untuk mengembangkan program berorientasi objek.
Sebabnya, OOP masih menjadi salah satu paradigma atau teknik
pemrograman yang banyak digunakan dalam pengembangan aplikasi.
Dengan paradigma OOP, kita dapat mudah memvisualisasikan kode
karena OOP sendiri mirip seperti skenario dalam kehidupan nyata.

Visualisasi di atas mencontohkan gambaran umum OOP di mana


terdapat sebuah blueprint mobil, komponen yang dimiliki mobil, dan
kemampuan yang dapat dilakukan oleh mobil. Dalam
OOP blueprint tersebut dikenal dengan Class (kelas), komponen
dikenal dengan nama atribut, kemampuan yang dimiliki dikenal
sebagai behaviour dan hasil realisasi dari sebuah blueprint tersebut
disebut object. Anda juga melihat gambaran OOP melalui ilustrasi
berikut.

Visualisasi di atas mencontohkan gambaran umum dari konsep OOP,


di mana terdapat sebuah blueprint Kucing, atribut yang dimiliki
Kucing, dan kemampuan yang dapat dilakukan oleh Kucing. Dalam
paradigma Object-Oriented Programming (OOP), class merupakan
sebuah blueprint yang dapat dikembangkan untuk membuat sebuah
objek. Blueprint ini merupakan sebuah template yang di dalamnya
menjelaskan perilaku dari objek itu (berupa properti ataupun function).
Dalam dunia pemrograman khususnya dalam paradigma OOP, kita
sering membuat banyak objek dengan jenis yang sama. Dengan
membuat blueprint ini, kita dapat mengurangi duplikasi kode dalam
membuat objek yang serupa.

4 Pilar dalam OOP

Sebelum mempelajari OOP lebih jauh, ada hal penting yang perlu Anda
perhatikan, yakni 4 pilar dalam OOP. Mengapa itu menjadi penting?
Coba bayangkan sebuah perusahaan besar seperti Google yang
menangani ratusan bahkan ribuan karyawannya. Dalam hal ini
tentunya Google memiliki serangkaian aturan dan kebijakan yang tepat
agar mencapai tujuan. Selaras dengan hal tersebut, ketika
mengembangkan sebuah perangkat lunak, pastinya kita akan memiliki
jumlah sistem yang banyak. Oleh karena itu, kita wajib menerapkan
sebuah aturan dan kebijakan dalam pengembangan tersebut guna
menghindari kompleksitas.

Untuk mencapainya, terdapat beberapa teknik yang dapat kita


gunakan seperti berikut.
1. Inheritance
Pewarisan adalah konsep di mana sebuah objek dapat mewarisi
sifat atau perilaku dari objek lain. Analoginya seperti hubungan
keluarga, di mana anak dapat mewarisi sifat atau karakteristik
tertentu dari orang tuanya. Pewarisan memungkinkan untuk
mendefinisikan objek baru berdasarkan objek yang sudah ada.
2. Encapsulation
Enkapsulasi diibaratkan sebuah kantong yang menyimpan
sesuatu. Dalam pemrograman, enkapsulasi berfungsi untuk
mengumpulkan data dan metode yang berhubungan ke dalam
sebuah objek. Saat menggunakan encapsulation, data dapat
diisolasi dan tidak dapat diakses langsung dari luar. Dengan
begini, kita cukup menggunakan data tersebut tanpa harus tahu
proses yang terjadi di dalamnya.
3. Abstraction
Abstraksi dapat dilakukan dengan menghilangkan kompleksitas
dan detail yang tidak perlu dari suatu objek sehingga hanya
menampilkan informasi penting saja. Sebagai contoh, saat
mengendarai mobil, pengemudi tidak perlu tahu detail
bagaimana mesin bekerja, tetapi hanya perlu memahami cara
menggunakan pedal gas, rem, dan setir. Abstraksi memudahkan
pemrograman dengan menyembunyikan detail implementasi
yang kompleks.
4. Polymorphism
Polimorfisme memungkinkan objek dengan tipe yang berbeda
untuk diproses dengan cara yang serupa. Ini mirip dengan
kemampuan manusia untuk beradaptasi dengan berbagai
situasi. Dalam pemrograman, polimorfisme dapat dilihat melalui
metode-metode yang memiliki nama yang sama, tetapi perilaku
yang berbeda tergantung pada objek yang memanggilnya.

Pada modul selanjutnya, kita akan membahas secara detail tentang


object, class, attribute, dan behaviour yang ada pada OOP. Selain itu,
kita akan belajar penerapan masing-masing pilar OOP yang sudah
dijelaskan secara lebih detail. Menarik, bukan? Yuk kita pelajari
bersama!
Object Everywhere
Pada sub-modul Data Types telah disebutkan bahwa pada Kotlin
semua bertindak sebagai objek di mana kita bisa memanggil member
function dan properti dari sebuah variabel. Objek merupakan hasil
realisasi dari sebuah blueprint atau class yang tentunya memiliki fungsi
dan juga properti sama seperti blueprint-nya. Artinya, dengan
membuat objek kita dapat mengakses fungsi dan properti yang
terdapat pada kelas tersebut.

Pada Kotlin, nilai primitif


seperti String, Integer, Char, Boolean merupakan sebuah Object. Hal
ini berbeda dengan bahasa pemrograman lain. Maka dari itu, terdapat
sebuah istilah yang terkenal di Kotlin, yaitu “Object Everywhere”.
Perhatikan kode berikut:

val someString = "Dicoding"

Pada kode tersebut kita melakukan pembuatan variabel yang juga


merupakan sebuah objek dengan nama someString. Objek tersebut
merupakan realisasi dari kelas String, maka objek someString memiliki
fungsi dan properti yang merupakan anggota dari kelas String.

Dari completion suggestion yang tersedia pada IntelliJ Idea, kita bisa
melihat beberapa fungsi yang dapat digunakan oleh objek someString.
Kita bisa menggunakan fungsi reverse() untuk membuat urutan huruf
disusun secara terbalik, fungsi toUpperCase() yang dapat membuat
huruf menjadi kapital atau fungsi toLowerCase() yang dapat membuat
menjadi huruf kecil.

fun main() {

val someString = "Dicoding"

println(someString.reversed())

println(someString.uppercase())
println(someString.lowercase())

/*

Output:

gnidociD

DICODING

dicoding

*/

Kita juga dapat mengubah tipe data dengan mengakses fungsi yang
tersedia dari sebuah objek String.

fun main() {

val someString = "123"

val someInt = someString.toInt()

val someOtherString = "12.34"

val someDouble = someOtherString.toDouble()

println(someInt is Int)

println(someDouble is Double)

/*
Output:

true

true

*/

Hasil dari output kode menunjukan nilai true pada kedua variabel
tersebut, yang artinya kita telah berhasil mengubah suatu tipe data
String ke tipe data lainnya dengan menggunakan fungsi yang terdapat
pada objek String.

Mungkin seperti itulah gambaran mengenai objek. Penting


digarisbawahi bahwa objek merupakan realisasi dari
sebuah blueprint yang tentunya memiliki properti dan fungsi yang
sama dengan blueprint-nya. Salah satu kegunaan objek adalah untuk
mengakses berbagai properti dan fungsi pada kelas.

Class
Seperti yang telah dijelaskan dalam pembahasan
objek, Class merupakan sebuah blueprint. Di dalam kelas ini kita
mendefinisikan sesuatu yang
merupakan attribute ataupun behaviour. Contohnya pada sebuah
kelas Kendaraan, atributnya berupa roda, warna, nomor kendaraan,
merk, dll. Sedangkan untuk behaviour nya yaitu maju, mundur, belok
kanan, belok kiri, berhenti. Contoh lainnya pada sebuah
kelas Hewan atributnya berupa nama, berat, umur, termasuk mamalia
atau bukan dll. Sedangkan untuk behaviour-nya bisa makan, tidur,
berjalan, dsb.

Setiap kelas memiliki atribut dan behaviour. Dalam


Kotlin, attributes lebih sering disebut dengan properties,
sedangkan behaviour atau fungsi yang di dalam class sering
disebut method.

Properti dalam sebuah kelas memiliki tipe data. Contoh, untuk properti
berat pada kelas Hewan dapat bertipe Double, nama dapat
bertipe String, umur dapat bertipe Int. dan indikasi mamalia dapat
bertipe Boolean. Selain itu, ia juga bisa memiliki sebuah behavior
seperti makan dan tidur. Jika kelas Hewan kita representasikan dalam
bentuk tabel maka akan terlihat seperti:

Animal
Properti Method
 name: String  eat()
 weight: Double  sleep()
 age: Int
 isMammal: Boolean

Pada pembahasan selanjutnya kita akan mencoba membuat sebuah


kelas berdasarkan bentuk tabel di atas. Namun, sebelum kita lanjut ke
pembahasan berikutnya, mari kita tekankan kembali beberapa hal
yang sudah kita pelajari.

 Class: sebuah blueprint yang terdapat properti dan fungsi di


dalamnya.
 Properties: karakteristik dari sebuah kelas, memiliki tipe data.
 Methods: kemampuan atau aksi dari sebuah kelas.

Membuat Class
Untuk mendefinisikan kelas dalam Kotlin, Anda cukup gunakan kata
kunci class diikuti dengan nama kelas yang akan dibuat. Mari kita buat
contoh kelas pada Kotlin.
class Animal

Sangat mudah, bukan? Sekarang kita tambahkan properti dan method


pada kelas tersebut.
class Animal() {

var name: String = "Kucing"

var weight: Double = 3.2

var age: Int = 2

var isMammal: Boolean = true

fun eat(){

println("$name makan!")
}

fun sleep() {

println("$name tidur!")

Pada kelas Animal di atas, kita bisa melihat bahwa di dalamnya


terdapat 4 properites dan 2 method Lalu, bagaimana cara membuat
sebuah objek dari kelas tersebut? Anda bisa perhatikan struktur kode
berikut.
val nameOfObject = NameOfClass()

Sama seperti variabel, Anda bisa gunakan val atau var diikuti dengan
nama objek yang akan dibuat. Setelah itu, gunakan tanda = untuk
menunjukkan bahwa kita akan menginisialisasi suatu objek dan
panggil nama kelas dengan tanda kurung di akhir. Tanda kurung
tersebut menunjukan bahwa kita membuat sebuah objek baru. Di
dalam tanda kurung, kita dapat menambahkan nilai properti sesuai
yang dibutuhkan pada primary constructor kelasnya.

Jika kita coba membuat objek dari kelas yang sudah kita buat, kodenya
akan terlihat seperti ini.

val dicodingCat = Animal()

Mari kita coba buat kode secara keseluruhan dengan ditambahkan


fungsi cetak untuk melihat nilai properti dalam objeknya.
val dicodingCat = Animal()

println("Nama: ${dicodingCat.name}, Berat: ${dicodingCat.weight}, Umur: ${dicodingCat.age},


mamalia: ${dicodingCat.isMammal}" )

dicodingCat.eat()

dicodingCat.sleep()

// Mengubah Properti dari class dicodingCat

dicodingCat.name = "Kucing Oren"

dicodingCat.weight = 6.0
dicodingCat.age = 3

println("Nama: ${dicodingCat.name}, Berat: ${dicodingCat.weight}, Umur: ${dicodingCat.age},


mamalia: ${dicodingCat.isMammal}" )

dicodingCat.eat()

dicodingCat.sleep()

Dengan menjalankan program tersebut, outputnya sebagai berikut.

Nama: Kucing, Berat: 3.2, Umur: 2, mamalia: true


Kucing makan!
Kucing tidur!
Nama: Kucing Oren, Berat: 6.0, Umur: 3, mamalia: true
Kucing Oren makan!
Kucing Oren tidur!

Properties
Sebuah kelas dalam Kotlin tentu memiliki properti. Masing - masing
kelas memiliki properti yang berbeda. Contoh sebelumnya pada
kelas Animal, properti yang dimiliki
berupa name, weight, age dan isMammal.

Sama seperti variabel yang sudah kita pelajari pada sub-modul Data
Types, properti dapat dideklarasikan sebagai nilai mutable dengan
menggunakan var atau sebagai nilai read-only dengan
menggunakan val.

Property Accessor

Secara standar ketika properti pada kelas dibuat mutable, maka Kotlin
akan menghasilkan fungsi getter dan setter pada properti tersebut.
Jika properti pada sebuah kelas dibuat read-only, Kotlin hanya akan
menghasilkan fungsi getter pada properti tersebut. Namun sebenarnya
Anda bisa membuat fungsi getter dan setter secara manual jika pada
kasus tertentu Anda perlu untuk override fungsi tersebut.

Perhatikan kode berikut

class Animal{
var name: String = "Dicoding Miaw"

fun main(){

val dicodingCat = Animal()

println("Nama: ${dicodingCat.name}" )

dicodingCat.name = "Goose"

println("Nama: ${dicodingCat.name}")

/*

output:

Nama: Dicoding Miaw

Nama: Goose

*/

Pada kode ${dicodingCat.name} sebenarnya terjadi proses


pemanggilan fungsi getter pada properti name. Namun kita tidak
melakukan override pada fungsi getter sehingga fungsi tersebut hanya
mengembalikan nilai name saja. Begitu juga pada
kode dicodingCat.name = "Goose" pada kode tersebut terjadi
pemanggilan fungsi setter pada properti name.

Tetapi jika kita melakukan override pada fungsi getter dan juga setter ,
maka kita dapat menambahkan kode lain pada fungsi getter sesuai
dengan kebutuhan. Mari kita coba modifikasi kode sebelumnya
menjadi:
class Animal{

var name: String = "Dicoding Miaw"

get(){

println("Fungsi Getter terpanggil")

return field

set(value){

println("Fungsi Setter terpanggil")

field = value

fun main(){

val dicodingCat = Animal()

println("Nama: ${dicodingCat.name}" )

dicodingCat.name = "Goose"

println("Nama: ${dicodingCat.name}")

/*

output:

Fungsi Getter terpanggil


Nama: Dicoding Miaw

Fungsi Setter terpanggil

Fungsi Getter terpanggil

Nama: Goose

*/

Urutan pendefinisian fungsi get() dan set() tidaklah penting, kita dapat
mendefinisikan fungsi get() tanpa mendefinisikan fungsi set() dan juga
sebaliknya. Yang terpenting pendeklarasiannya dilakukan setelah
mendeklarasikan properti tersebut. Pada fungsi get(), kita perlu
mengembalikan nilai sesuai tipe data dari propertinya atau kita dapat
mengembalikan nilai dari properti itu sendiri dengan
menggunakan keyword field. Sedangkan untuk fungsi set() kita
memerlukan sebuah parameter. Ini merupakan sebuah nilai baru yang
nantinya akan dijadikan nilai properti. Pada kode di atas parameter
tersebut ditetapkan dengan nama value.

Lateinit & Lazy Property


Seperti yang Anda pelajari sebelumnya, Anda dapat membuat variabel
atau property dengan cara menginisialisasi nilainya secara langsung
seperti ini.

val name: String = "Dicoding Miaw"

Lalu, bagaimana jika kita tidak ingin menginisialisasi nilainya secara


langsung? Misalnya, ada sebuah kondisi yang menyebabkan nilainya
baru akan diinisialisasi nanti setelah mendapatkan data dari
constructor atau karena kita perlu memakai variabel tersebut di fungsi
lain atau yang biasa disebut dengan global variable.

Masalahnya, Anda tidak bisa menggunakan pendekatan seperti dalam


bahasa pemrograman Java yang bisa menuliskan variabel saja tanpa
nilai seperti contoh kode di bawah ini. Hal ini karena setiap variabel di
Kotlin harus diinisialisasi di awal.
val name: String // Error! Variable 'name' must be initialized

Nah, salah satu alternatif solusi yang bisa dipakai adalah mengisinya
dengan nilai null terlebih dahulu seperti berikut.

var name: String? = null

fun main() {

name = "Dicoding Miaw"

print(name?.length)

Namun, pendekatan ini memerlukan safe call operator (?.) setiap kali
mengakses property atau fungsi di dalamnya. Tentunya ini menambah
pekerjaan untuk mengecek apakah variabel tersebut null atau tidak,
padahal kita sudah yakin bahwa variabel tersebut sudah pasti ada
nilainya nanti.

Lalu, bagaimana supaya supaya variabel tersebut tidak null, tetapi


tetap bisa diinisialisasi di lain waktu?

Untuk mengatasinya, Kotlin memiliki mekanisme untuk menunda


proses inisialisasi sampai variabel tersebut benar-benar dibutuhkan,
yakni dengan menggunakan lateinit dan lazy. Mari kita bedah satu per
satu!

Lateinit

Lateinit merupakan keyword yang ditambahkan sebelum variabel


untuk membuat proses inisialisasi bisa ditunda. Berikut ini contohnya.

lateinit var name: String

fun main() {

name = "Dicoding Miaw"


print(name.length)

Catatan:
Hal yang perlu diperhatikan adalah lateinit harus disandingkan dengan
keyword var (tidak bisa menggunakan val). Hal ini berbeda dengan
Lazy property yang nanti akan dibahas.

Property Delegation
Pengelolaan properti kelas baik itu memberikan atau mengubah
sebuah nilai dapat didelegasikan kepada kelas lain. Dengan ini kita
dapat meminimalisir boilerplate dalam penulisan getter dan setter (jika
properties menggunakan var) pada setiap kelas yang kita buat.
Sebagai contoh, kita memiliki tiga buah kelas yang di dalamnya
memiliki satu properti String. Jika kita ingin
menerapkan getter dan setter pada setiap properti kelasnya, maka kita
perlu menuliskan getter dan setter tersebut pada seluruh kelas. Hal
tersebut dapat mengurangi efisiensi dalam menuliskan kode karena
terlalu banyak kode yang harus kita tulis secara berulang. Solusinya,
kita perlu membuat sebuah kelas yang memang bertugas untuk
mengatur atau mengelola fungsi getter dan setter untuk sebuah
properti kelas. Teknik tersebut pada Kotlin dinamakan Delegate.

Sebelum mendelegasikan sebuah properti kita perlu membuat kelas


delegasi terlebih dahulu. Mari kita buat sebuah kelas delegasi.

import kotlin.reflect.KProperty

class DelegateName {

private var value: String = "Default"

operator fun getValue(classRef: Any?, property: KProperty<*>) :


String {
println("Fungsi ini sama seperti getter untuk properti $
{property.name} pada class $classRef")

return value

operator fun setValue(classRef: Any?, property: KProperty<*>,


newValue: String){

println("Fungsi ini sama seperti setter untuk properti $


{property.name} pada class $classRef")

println("Nilai ${property.name} dari: $value akan berubah menjadi


$newValue")

value = newValue

Kemudian untuk mendelegasikan sebuah properti kelas, kita


gunakan keyword by dalam menginisialisasi properti tersebut
kemudian diikuti dengan namanya. Perhatikan kode berikut:

class Animal {

var name: String by DelegateName()

Dengan begitu nilai properti name dikelola melalui


kelas DelegateName. Kita dapat mendelegasikan banyak properti yang
terdapat pada banyak kelas kepada satu kelas Delegate saja.
Perhatikan kode berikut untuk untuk lebih jelasnya:

class Animal {

var name: String by DelegateName()


}

class Person {

var name: String by DelegateName()

class Hero {

var name: String by DelegateName()

Mari kita membuat sebuah objek, ubah dan akses nilai propertinya
pada setiap kelas, kemudian jalankan. Maka hasilnya akan seperti pada
kode berikut:

fun main() {

val animal = Animal()

animal.name = "Dicoding Miaw"

println("Nama Hewan: ${animal.name}")

val person = Person()

person.name = "Dimas"

println("Nama Orang: ${person.name}")

val hero = Hero()

hero.name = "Gatotkaca"
println("Nama Pahlawan: ${hero.name}")

/*

output:

Fungsi ini sama seperti setter untuk properti name pada class
Animal@17f052a3

Nilai name dari: Default akan berubah menjadi Dicoding Miaw

Fungsi ini sama seperti getter untuk properti name pada class
Animal@17f052a3

Nama Hewan: Dicoding Miaw

Fungsi ini sama seperti setter untuk properti name pada class
Person@2e0fa5d3

Nilai name dari: Default akan berubah menjadi Dimas

Fungsi ini sama seperti getter untuk properti name pada class
Person@2e0fa5d3

Nama Orang: Dimas

Fungsi ini sama seperti setter untuk properti name pada class
Hero@5010be6

Nilai name dari: Default akan berubah menjadi Gatotkaca

Fungsi ini sama seperti getter untuk properti name pada class
Hero@5010be6

Nama Pahlawan: Gatotkaca

*/
Pada contoh di atas, delegasi hanya dapat digunakan oleh properti
yang memiliki tipe data String. Namun kita juga dapat membuat
sebuah delegasi kelas umum yang dapat digunakan oleh seluruh tipe
data dengan memanfaatkan tipe data Any.

import kotlin.reflect.KProperty

class DelegateGenericClass {

private var value: Any = "Default"

operator fun getValue(classRef: Any, property: KProperty<*>): Any {

println("Fungsi ini sama seperti getter untuk properti $


{property.name} pada class $classRef")

return value

operator fun setValue(classRef: Any, property: KProperty<*>,


newValue: Any) {

println("Nilai ${property.name} dari: $value akan berubah menjadi


$newValue")

value = newValue

class Animal {
var name: Any by DelegateGenericClass()

var weight: Any by DelegateGenericClass()

var age: Any by DelegateGenericClass()

Kemudian mari kita membuat sebuah objek dari kelas Animal, ubah
dan akses nilai propertinya kemudian jalankan. Maka hasilnya akan
seperti pada kode berikut:

fun main(){

val animal = Animal()

animal.name = "Dicoding cat"

animal.weight = 6.2

animal.age = 1

println("Nama: ${animal.name}")

println("Berat: ${animal.weight}")

println("Umur: ${animal.age} Tahun")

/*

output:

Nilai name dari: Default akan berubah menjadi Dicoding cat

Nilai weight dari: Default akan berubah menjadi 6.2

Nilai age dari: Default akan berubah menjadi 1


Fungsi ini sama seperti getter untuk properti name pada class
Animal@17f052a3

Nama: Dicoding cat

Fungsi ini sama seperti getter untuk properti weight pada class
Animal@17f052a3

Berat: 6.2

Fungsi ini sama seperti getter untuk properti age pada class
Animal@17f052a3

Umur: 1 Tahun

*/

Perhatikan kode diatas, kita telah memberikan nilai pada setiap


properti dengan tipe data yang berbeda. Tetapi
dengan DelegateGenericClass(), pengelolaan properti dapat digunakan
pada seluruh tipe data properti.

Sip! Itulah penjelasan terkait property delegation yang bakal sering


Anda temui ketika membuat aplikasi Android nanti. Jika tertarik untuk
mendalami lebih lanjut, Anda dapat melihat beberapa referensi
berikut.

 How to Kotlin - from the lead Kotlin language designer (Google


I/O '18)

Primary Constructor
Ketika suatu objek dibuat, semua properti pada kelas tersebut harus
memiliki nilai. Kita dapat langsung menginisialisasi pada properti
tertentu atau menginisialisasinya melalui constructor (konstruktor).
Konstruktor merupakan fungsi spesial yang digunakan untuk
menginisialisasi properti yang terdapat pada kelas tersebut.
Terdapat 2 (dua) tipe konstruktor pada Kotlin, yaitu primary
constructor dan secondary constructor. Yuk, kita coba
mempelajarinya bersama.

Primary Constructor
Seperti namanya, jika akan membuat suatu objek dari sebuah kelas
dan kelas tersebut memiliki primary constructor di dalamnya, kita harus
mengirim nilai sesuai properti yang dibutuhkan. Penulisan primary
constructor mirip seperti parameter pada fungsi. Properti cukup
dituliskan pada header class diawali dengan var atau val. Perhatikan
kode berikut.

class Animal(val name: String, val weight: Double, val age: Int, val
isMammal: Boolean)

Pada baris kode tersebut, kita tidak hanya membuat sebuah kelas,
tetapi sekaligus menambahkan sebuah primary constructor pada kelas
tersebut. Sekarang mari kita coba membuat objek dari kelas tersebut.

fun main(){

val dicodingCat = Animal("Dicoding Miaw", 4.2, 2, true)

println("Nama: ${dicodingCat.name}, Berat: ${dicodingCat.weight},


Umur: ${dicodingCat.age}, mamalia: ${dicodingCat.isMammal}" )

/*

output:

Nama: Dicoding Miaw, Berat: 4.2, Umur: 2, mamalia: true

*/

Perhatikan kode di atas. Karena kelas Animal memiliki primary


constructor, kita perlu mengirimkan beberapa nilai
yaitu name, weight, age, dan isMammal saat membuat objeknya.
Primary constructor juga dapat memiliki nilai default jika kita tidak
menetapkan nilai untuk parameter tersebut. Contohnya, kita bisa
memberikan nilai default terhadap properti age. Sehingga, ketika
pembuatan objek, pengiriman nilai age pada primary
constructor bersifat opsional.

Untuk membuat nilai default pada sebuah primary constructor, kita


perlu menginisialisasi nilai pada saat kita menuliskan properti pada
kelas. Perhatikan kode berikut.

class Animal(var name: String, var weight: Double, var age: Int = 0, var
isMammal: Boolean = true)

Kode tersebut menunjukan bahwa kita membuat nilai default pada


properti age yang bernilai 0 dan isMammal yang bernilai true.
Sehingga, pada pembuatan objek Animal, kita bisa mengirimkan
nilai name dan weight saja pada primary constructor. Mari kita coba
membuat objek dengan memanfaatkan nilai default pada konstruktor.

fun main(){

val dicodingCat = Animal("Dicoding Miaw", 4.2)

println("Nama: ${dicodingCat.name}, Berat: ${dicodingCat.weight},


Umur: ${dicodingCat.age}, mamalia: ${dicodingCat.isMammal}" )

/*

output:

Nama: Dicoding Miaw, Berat: 4.2, Umur: 0, mamalia: true

*/

Hasil dari kode tersebut memperlihatkan bahwa


properti age dan isMammal memiliki nilai default. Sekali lagi, properti
tersebut bersifat opsional sehingga kita tetap dapat mengirimkan nilai
pada properti walaupun telah memiliki nilai default.

Kita juga dapat secara eksplisit memilih properti yang ingin kita
berikan nilai dengan menambahkan nama properti dan
tanda = sebelum mengisikan nilai properti.

val dicodingCat = Animal("Dicoding Miaw", 4.2, isMammal = true)

Init block
Kotlin menyediakan blok init yang memungkinkan kita untuk
menuliskan properti di dalam body class ketika kita
menggunakan primary constructor. Memang, memiliki kode banyak di
dalam body class bukanlah hal yang baik. Kotlin bertujuan agar kita
dapat menuliskan kode seminimal mungkin. Tapi blok init di sini
memiliki beberapa fungsi selain menginisialisasi properti kelas. satu
fungsi lainnya adalah untuk membantu dalam memvalidasi sebuah
nilai properti sebelum diinisialisasi. Pada kelas Animal contohnya, kita
dapat melakukan verifikasi bahwa berat dan umur hewan tidak boleh
bernilai kurang dari nol.

Untuk membuatnya, kita dapat menggunakan keyword init kemudian


inisialisasikan semua properti di dalam blok tersebut dengan
parameter kelas.

class Animal(pName: String, pWeight: Double, pAge: Int, pIsMammal:


Boolean){

val name: String

val weight: Double

val age: Int

val isMammal: Boolean

init {

weight = if(pWeight < 0) 0.1 else pWeight


age = if(pAge < 0) 0 else pAge

name = pName

isMammal = pIsMammal

Primary constructor dan init harus saling terhubung.


Fungsi init dijalankan ketika suatu objek dibuat dengan
menggunakan primary constructor. Mari kita coba untuk membuatnya.

fun main() {

val dicodingCat = Animal("Dicoding Miaw", 4.2, 2, true)

println("Nama: ${dicodingCat.name}, Berat: ${dicodingCat.weight},


Umur: ${dicodingCat.age}, mamalia: ${dicodingCat.isMammal}")

/*

output:

Nama: Dicoding Miaw, Berat: 4.2, Umur: 2, mamalia: true

*/

Perhatikan juga penamaan antara properti pada body class dan


parameter pada head class penamaan antara keduanya harus berbeda
agar tidak terjadi ambiguitas. Lantas bagaimana jika kita ingin
penamaan keduanya sama? Untuk menghindari ambiguitas kita dapat
menggunakan keyword this dalam menginisialisasi properti tersebut
dalam blok init.

class Animal(name: String, weight: Double, age: Int, isMammal:


Boolean) {
val name: String

val weight: Double

val age: Int

val isMammal: Boolean

init {

this.weight = if(weight < 0) 0.1 else weight

this.age = if(age < 0) 0 else age

this.name = name

this.isMammal = isMammal

Kata kunci this tersebut merujuk kepada suatu kelas. Maksudnya


adalah ketika menggunakan kelas tersebut dan diikuti dengan nama
properti, berarti kita menunjuk pada properti yang terdapat pada
kelas. Dengan begitu, tidak akan ada ambiguitas walaupun kita
menggunakan penamaan yang sama antara properti dan
parameter primary constructor.

Secondary Constructor
Secondary constructor digunakan ketika kita ingin menginisialisasi
sebuah kelas dengan cara yang lain. Anda dapat membuat lebih dari
satu secondary constructor. Sebagai contoh, kita bisa menambahkan
secondary constructor pada kelas Animal:

class Animal(name: String, weight: Double, age: Int) {


val name: String

val weight: Double

val age: Int

var isMammal: Boolean

init {

this.weight = if(weight < 0) 0.1 else weight

this.age = if(age < 0) 0 else age

this.name = name

this.isMammal = false

constructor(name: String, weight: Double, age: Int, isMammal:


Boolean) : this(name, weight, age) {

this.isMammal = isMammal

fun main() {

val dicodingCat = Animal("Dicoding Miaw", 2.5, 2, true)

println("Nama: ${dicodingCat.name}, Berat: ${dicodingCat.weight},


Umur: ${dicodingCat.age}, mamalia: ${dicodingCat.isMammal}")
val dicodingBird = Animal("Dicoding tweet", 0.5, 1)

println("Nama: ${dicodingBird.name}, Berat: ${dicodingBird.weight},


Umur: ${dicodingBird.age}, mamalia: ${dicodingBird.isMammal}")

/*

output:

Nama: Dicoding Miaw, Berat: 2.5, Umur: 2, mamalia: true

Nama: Dicoding tweet, Berat: 0.5, Umur: 1, mamalia: false

*/

Dengan begitu, objek Animal dapat diinisialisasi dengan secondary


constructor ketika nilai name, weight, age dan isMammal tersedia.
Tetapi jika nilai isMammal tidak tersedia, primary constructor lah yang
akan digunakan dan nilai isMammal dapat diinisialisasi pada
blok init dengan nilai default.

Default Constructor
Kotlin secara otomatis membuat sebuah default constructor pada kelas
jika kita tidak membuat sebuah konstruktor secara manual. Perhatikan
kode berikut:

class Animal{

val name: String = "Dicoding Miaw"

val weight: Double = 4.2

val age: Int = 2

val isMammal: Boolean = true


}

fun main(){

val dicodingCat = Animal()

println("Nama: ${dicodingCat.name}, Berat: ${dicodingCat.weight},


Umur: ${dicodingCat.age}, mamalia: ${dicodingCat.isMammal}" )

/*

output:

Nama: Dicoding Miaw, Berat: 4.2, Umur: 2, mamalia: true

*/

Ketika kita membuat sebuah objek, default konstruktor akan dipanggil.


Konstruktor tersebut akan menginisialisasi properti yang terdapat
pada kelas dengan nilai default.

Visibility Modifiers
Kali ini kita akan mengenal beberapa tentang visibility modifiers atau
hak akses pada Kotlin. Tentunya, tidak semua properti dan method
pada sebuah kelas memiliki hak akses publik. Ada beberapa yang
hanya dapat diakses dari dalam dan ada yang dapat diakses dari luar
kelasnya. Dengan menentukan hak akses tersebut, kita dapat
membatasi akses data pada sebuah kelas, inilah yang disebut
dengan encapsulation pada salah satu pilar OOP.

Berikut macam-macam hak akses dan penjelasan singkatnya yang


dapat digunakan pada Kotlin:
 Public: Hak akses yang cakupannya paling luas. Anggota yang
diberi modifier ini dapat diakses dari manapun.
 Private: Hak akses yang cakupannya paling terbatas. Anggota
yang menerapkannya hanya dapat diakses pada scope yang
sama.
 Protected: Hak akses yang cakupannya terbatas pada hirarki
kelas. Anggota hanya dapat diakses pada kelas turunannya atau
kelas itu sendiri.
 Internal: Hak akses yang cakupannya terbatas pada satu modul.
Anggota yang menggunakannya tidak dapat diakses diluar dari
modulnya tersebut.
Semua modifier tersebut bisa digunakan untuk kelas, objek,
konstruktor, fungsi, beserta properti yang ada di dalamnya. Kecuali
modifier protected yang hanya bisa digunakan untuk anggota di dalam
sebuah kelas dan interface. Protected tidak bisa digunakan
pada package member seperti kelas, objek, dan yang lainnya. Setelah
mengetahui pentingnya hak akses, selanjutnya kita akan membahas
bagaimana kita menentukan hak akses public, private, protected dan
internal pada Kotlin.

Public
Berbeda dengan bahasa pemrograman umumnya, default
modifier pada Kotlin adalah public. Ketika sebuah anggota memiliki
hak akses public maka anggota tersebut dapat diakses dari luar
kelasnya melalui sebuah objek kelas tersebut.

Pada pembahasan sebelumnya kita sudah memiliki sebuah


kelas Animal dengan properti publik
seperti name, age, weight dan isMammal. Properti tersebut dapat kita
akses dari luar kelas Animal.
Dari completion suggestion terlihat bahwa properti tersebut dapat kita
akses di luar dari kelasnya.

Private
Ketika suatu anggota memiliki hak akses private, maka anggota
tersebut tidak dapat diakses dari luar scope-nya. Untuk
menggunakan modifier private kita perlu
menambahkan keyword private seperti contoh berikut:

private val name: String,

Mari kita coba ubah hak akses pada seluruh properti


kelas Animal menjadi private.

class Animal(

private val name: String,

private val weight: Double,

private val age: Int,

private val isMammal: Boolean

)
fun main() {

val dicodingCat = Animal("Dicoding Miaw", 2.5, 2)

println("Nama: ${dicodingCat.name}, Berat: ${dicodingCat.weight},


Umur: ${dicodingCat.age}, mamalia: ${dicodingCat.isMammal}")

Dengan menggunakan hak akses private, maka kita tidak diizinkan


untuk mengakses properti pada kelas Animal tersebut dari luar
kelasnya. Anda akan berjumpa dengan eror Cannot access '[PROPERTY]':
it is private in 'Animal'. Satu satunya cara untuk mengakses properti
private dari sebuah kelas adalah dengan menambahkan
fungsi getter dan setter secara manual.
Fungsi getter dan setter sebenarnya dihasilkan secara otomatis oleh
Kotlin ketika properti tersebut memiliki hak akses public tetapi tidak
untuk private. Untuk penulisan getter dan setter pada hak akses private
sama seperti fungsi pada umumnya:

fun getName() : String {

return name

fun setName(newName: String) {

name = newName

Fungsi getName() bertujuan untuk mengembalikan nilai name yang


memiliki tipe data String. Kemudian fungsi setName() bertujuan untuk
mengubah nilai properti name dengan nilai baru.
Fungsi setName() membutuhkan satu parameter bertipe String yang
nantinya akan dimasukkan nilainya ke dalam properti name.

Mari kita coba menerapkannya.


class Animal(private var name: String, private val weight: Double,
private val age: Int, private val isMammal: Boolean = true) {

fun getName() : String {

return name

fun setName(newName: String) {

name = newName

fun main() {

val dicodingCat = Animal("Dicoding Miaw", 2.5, 2)

println(dicodingCat.getName())

dicodingCat.setName("Gooose")

println(dicodingCat.getName())

/*

output:

Dicoding Miaw
Gooose

*/

Pada kode di atas, terlihat bahwa kita berhasil mengubah nilai


properti name dari nilai awal yang kita inisialisasikan pada konstruktor.
Ia menjadi nilai baru yang kita tentukan dengan menggunakan
fungsi setName().

Protected
Hak akses protected mirip seperti private, namun pembatasannya
lebih luas dalam sebuah hirarki kelas. Hak akses protected digunakan
ketika kita menginginkan sebuah anggota dari induk kelas dapat
diakses hanya oleh kelas yang merupakan turunannya. Perhatikan
kode di bawah ini untuk contoh penggunaan hak akses protected.

open class Animal(val name: String, protected val weight: Double)

class Cat(pName: String, pWeight: Double) : Animal(pName, pWeight)

Pada kode tersebut, properti weight pada kelas Animal memiliki hak
akses protected. Kita tetap bisa mengaksesnya dari kelas Cat yang
termasuk dalam hirarki kelas Animal. Namun kita tidak dapat
mengakses properti tersebut secara langsung dari luar hirarki
kelasnya. Eror akan terjadi jika kita melakukan hal tersebut.

open class Animal(val name: String, protected val weight: Double)

class Cat(pName: String, pWeight: Double) : Animal(pName, pWeight)

fun main() {
val cat = Cat("Dicoding Miaw", 2.0)

println("Nama Kucing: ${cat.name}")

println("Berat Kucing: ${cat.weight}") // error: expecting a top level


declaration

Internal
Internal merupakan hak akses baru yang diperkenalkan pada Kotlin.
Hak akses ini membatasi suatu anggota untuk dapat diakses hanya
pada satu modul. Berikut ini contoh penggunaan hak akses internal:

internal class Animal(val name: String)

Pada contoh di atas, kelas Animal telah ditetapkan sebagai kelas


internal, maka kelas tersebut hanya dapat diakses dari modul yang
sama. Hak akses ini sangat berguna ketika kita mengembangkan
sebuah aplikasi yang memiliki beberapa modul di dalamnya.

Overloading
Di awal, kita sudah mengenal salah satu pilar dari OOP, yakni
Polymorphism. Polymorphism merupakan kemampuan objek, variabel,
atau fungsi yang dapat memiliki berbagai bentuk. Alhasil, kita dapat
mengembangkan sebuah program secara umum, bukan spesifik.

Polymorphism dapat digambarkan seperti seorang yang menguasai


dan mampu berbicara dalam beberapa bahasa. Nah di sini, seseorang
yang bertindak sebagai obyek dan kemampuan dia berbicara
merupakan sebuah Polymorphism. Contoh lainnya adalah
smartphone. Selain sebagai alat komunikasi, smartphone yang
bertindak sebagai objek dapat digunakan sebagai kamera, pemutar
musik, dan radio.

Dari sisi kode, polimorphism dapat diartikan sebagai sebuah nama


fungsi yang dapat melakukan hal yang yang bermacam-macam.
Bagaimana itu bisa terjadi? Caranya yaitu dengan membuat
Overloading. Overloading merupakan kondisi di mana kita bisa
membuat 2 (dua) atau lebih fungsi yang memiliki jumlah, tipe, atau
urutan parameter yang berbeda di dalam sebuah class.

Berikut merupakan contoh overloading fungsi eat() pada sebuah


kelas Animal.

class Animal(private var name: String) {

fun eat() {

println("$name makan!")

fun eat(typeFood: String) {

println("$name memakan $typeFood!")

fun eat(typeFood: String, quantity: Double) {

println("$name memakan $typeFood sebanyak $quantity grams!")

fun sleep() {

println("$name tidur!")

Pada kelas Animal terdapat beberapa fungsi dengan penamaan yang


sama, tetapi tidak menyebabkan eror. Sebabnya, fungsi tersebut
memiliki parameter yang berbeda sehingga tidak akan terjadi
ambiguitas dalam penggunaan fungsi tersebut. Mari kita coba buat
sebuah objek dari kelas tersebut dan mengakses fungsinya satu per
satu.

fun main() {

val dicodingCat = Animal("Dicoding Miaw")

dicodingCat.eat()

dicodingCat.eat("Ikan Tuna")

dicodingCat.eat("Ikan Tuna", 450.0)

/*

Output:

Dicoding Miaw makan!

Dicoding Miaw memakan Ikan Tuna!

Dicoding Miaw memakan Ikan Tuna sebanyak 450.0 grams!

*/

Fungsi eat() yang pertama dapat digunakan tanpa mengirimkan


parameter apapun. Sedangkan fungsi eat() yang kedua kita
mengirimkan sebuah parameter String sebagai nilai typeFood. Dan
fungsi eat() yang terakhir membutuhkan 2 (dua) buah
parameter, typeFood dan quantity.

Overloading pada fungsi merupakan sebuah fitur yang sangat powerful.


Untuk dapat lebih memahami betapa pentingnya overloading, mari kita
buat sebuah kelas Calculator yang di dalamnya memiliki fungsi
matematika dengan menerapkan overloading pada sebuah fungsi.

class Calculator {

fun add(value1: Int, value2: Int) = value1 + value2

fun add(value1: Int, value2: Int, value3: Int) = value1 + value2 +


value3

fun add(value1: Double, value2: Double) = value1 + value2

fun add(value1: Float, value2: Float) = value1 + value2

fun min(value1: Int, value2: Int) = if (value1 < value2) value1 else
value2

fun min(value1: Double, value2: Double) = if (value1 < value2) value1


else value2

Kemudian kita buat sebuah objek Calculator pada main() dan


mengakses fungsi yang berada pada kelas tersebut.

fun main() {

val calc = Calculator()

println(calc.add(2, 4))

println(calc.add(2.5, 2.2))

println(calc.add(6f, 7f))

println(calc.add(1, 2, 3))
println(calc.min(9, 2))

println(calc.min(17.2, 18.3))

/*

output

4.7

13.0

17.2

*/

Pada contoh yang kita buat, fungsi add(2, 4) memanggil


fungsi add yang memiliki parameter Integer, fungsi add(2.5,
2.2) memanggil fungsi add yang memiliki parameter Double, begitu
juga dengan yang lainnya.

Inheritances
Dalam gambaran dunia nyata, banyak objek yang berbeda tetapi
punya kesamaan atau kemiripan tertentu. Contohnya Kucing dan
Kambing memiliki banyak kesamaan karena objek tersebut merupakan
hewan. Kucing merupakan hewan mamalia, begitu juga dengan
kambing. Mungkin yang membedakan objek tersebut adalah cara
mereka mencari makanan dan jenis makanan yang dimakan. Sama
halnya pada OOP, beberapa objek yang berbeda bisa saja memiliki
kesamaan dalam hal tertentu. Di situlah
konsep inheritance atau pewarisan yang merupakan salah satu pilar
dari OOP harus diterapkan. Pewarisan dapat mencegah kita
melakukan perulangan kode. Untuk lebih memahaminya lihatlah
contoh bagan pada sebuah kelas berikut:

Cat Fish Snake


+ name: String + name: String + name: String

+ furColor: String + scaleColor: String + skinColor: String

+ weight: Double + weight: Double + weight: Double

+ age: Integer + age: Integer + age: Integer

+ numberOfFeet: Integer + numberOfFin: Integer + isToxic: Boolean

+ isCarnivore: Boolean + isCarnivore: Boolean + isCarnivore: Bo


- eat() - eat() - eat()

- sleep() - sleep() - sleep()

- playWithHuman() - swim() - bite()


Pada bagan tersebut dapat kita lihat pada
kelas Cat, Fish dan Snake memiliki beberapa properti yang sama
seperti name, weight, age, isCarnivore dan juga memiliki beberapa
fungsi yang sama seperti eat() dan sleep(). Jika kita ubah diagram kelas
Kucing menjadi sebuah kode maka akan menjadi seperti ini:

class Cat(val name: String, val furColor: String, val weight: Double, val
age: Integer, val numberOfFeet: Integer, val isCarnivore: Boolean) {

fun eat(){

println("$name sedang makan!")

fun sleep() {

println("$name sedang tidur!")


}

fun playWithHuman() {

println("$name bermain dengan Manusia!")

Tidak ada masalah dengan kode tersebut, tetapi ketika kita akan
membuat kelas dari diagram lainnya contohnya Fish maka kita harus
menuliskan ulang properti seperti name, weight, age dan properti atau
fungsi yang sama lainnya. Hal ini dapat mengurangi efisiensi dalam
menuliskan kode.

Dengan teknik inheritance, kita bisa mengelompokkan properti dan


fungsi yang sama. Caranya , buat sebuah kelas baru yang nantinya
akan diturunkan sifatnya pada sebuah kelas:

Animal
+ name: String

+ weight: Double

+ age: Integer

+ isCarnivore: Boolean
- eat()

- sleep()
Cat Fish Snake
+ furColor: String + scaleColor: String + skinColor: String

+ numberOfFeet: Integer + numberOfFin: Integer + isToxic: Boolean


- playWithHuman() - swim() - bite()
Ketika kelas Animal telah dibuat, kelas lainnya dapat
melakukan extends pada kelas tersebut. Dalam pewarisan,
kelas Animal (main class) dapat disebut sebagai super atau parent class.
Kelas yang melakukan extends pada kelas tersebut disebut child class.
Dalam Kotlin untuk melakukan extends pada sebuah kelas dapat
dilakukan dengan tanda : seperti contoh berikut:

class ChildClass : ParentClass {

Mari kita buat kelas Animal yang akan berperan sebagai parent
class seperti berikut:

open class Animal(val name: String, val weight: Double, val age: Int, val
isCarnivore: Boolean){

open fun eat(){

println("$name sedang makan!")

open fun sleep(){

println("$name sedang tidur!")

Untuk membuat sebuah super atau parent class kita akan


membutuhkan open class. Kelas pada Kotlin
secara default bersifat final, oleh karena itu kita harus mengubahnya
menjadi open class sebelum melakukan extends kelas tersebut.

Ubahlah kelas Cat dengan melakukan extends pada


kelas Animal seperti berikut:
class Cat(pName: String, pWeight: Double, pAge: Int, pIsCarnivore:
Boolean, val furColor: String, val numberOfFeet: Int)

: Animal(pName, pWeight, pAge, pIsCarnivore) {

fun playWithHuman() {

println("$name bermain bersama Manusia !")

override fun eat(){

println("$name sedang memakan ikan !")

override fun sleep() {

println("$name sedang tidur di bantal !")

Perhatikan bahwa pada kode di atas kita menggunakan


keyword override untuk mengambil alih atau mengganti implementasi
fungsi dari parent class. Jika dilihat, itu artinya sebuah fungsi dengan
nama yang sama bisa memiliki perilaku yang berbeda. Masih ingatkah
konsep apakah ini? Ya, betul! Ini juga termasuk salah satu bagian dari
konsep Polymorphism. Kita menyebutnya dengan teknik Overriding.

Berbeda dengan Overloading yang dalam penentuan keputusan


pemanggilan fungsi dibuat selama proses kompilasi (compile time),
keputusan pemanggilan fungsi pada Overriding dibuat saat program
sedang berjalan (runtime). Hal ini karena kompiler tidak tahu objek
manakah yang memanggil fungsi tersebut, apakah Animal atau Cat
sampai program tersebut dijalankan.

Dengan begitu, kita dapat mengubah implementasi pada kelas Cat


sesuai dengan preferensi yang kita mau dan menampilkan hasil yang
berbeda ketika fungsi turunan dari parent class diambil.

fun main(){

val dicodingCat = Cat("Dicoding Miaw", 3.2, 2, true, "Brown", 4)

dicodingCat.playWithHuman()

dicodingCat.eat()

dicodingCat.sleep()

/*

output:

Dicoding Miaw bermain bersama Manusia !

Dicoding Miaw sedang memakan ikan !

Dicoding Miaw sedang tidur di bantal !

*/

Lalu, bagaimana jika Anda tidak ingin mengambil alih penuh, tetapi
hanya ingin menambahkan implementasi dari yang sudah di parent
class? Jawabannya adalah dengan menggunakan keyword super.

open class Animal(val name: String){

open fun eat(){


println("$name sedang makan!")

class Cat(pName: String) : Animal(pName) {

override fun eat(){

super.eat()

println("$name sedang memakan ikan !")

fun main(){

val dicodingCat = Cat("Dicoding Miaw")

dicodingCat.eat()

/*

output:

Dicoding Miaw sedang makan!

Dicoding Miaw sedang memakan ikan !


*/

Dengan begitu, kedua implementasi, baik di parent class (kelas induk)


maupun di subclass (kelas turun) tetap dijalankan. Anda akan sering
menemukan konsep seperti ini ketika membuat aplikasi Android nanti.
Jadi, pahami baik baik yah!

Abstract Class

Kita lanjut ke salah satu pilar lain pada OOP, yakni Abstraction.
Abstraction adalah konsep di mana Anda menyembunyikan detail
tertentu dari implementasi suatu objek dan hanya menunjukkan
fungsionalitas yang relevan atau penting bagi pengguna objek
tersebut. Jadi, pada kelas induknya kita hanya mendefinisikan nama
method dan property-nya saja, untuk implementasinya nanti
diserahkan ke kelas turunannya. Hal ini berbeda dengan konsep
inheritance sebelumnya yang seluruh method dan property sudah
memiliki implementasi pada kelas induk.

Untuk menerapkan Abstraction, kita bisa menggunakan Abstract Class


dan Interface pada bahasa Kotlin. Mari kita pahami satu per satu.

Abstract Class
Seperti namanya, abstract merupakan gambaran umum dari sebuah
kelas. Ia tidak dapat direalisasikan dalam sebuah objek. Pada sub-
modul sebelumnya kita sudah mempunyai kelas Animal. Secara
harfiah hewan merupakan sebuah sifat. Kita tidak tahu bagaimana
objek hewan tersebut. Kita tahu bentuk kucing, ikan dan ular seperti
apa tetapi tidak untuk hewan. Maka dari itu konsep abstract class perlu
diterapkan agar kelas Animal tidak dapat direalisasikan dalam bentuk
objek namun tetap dapat menurunkan sifatnya kepada child class-nya.

Untuk menjadikan sebuah kelas abstract, kita hanya perlu


menambahkan keyword abstract sebelum menuliskan nama kelas:

abstract class Animal(var name: String, var weight: Double, var age: Int,
var isCarnivore: Boolean){
fun eat(){

println("$name sedang makan !")

fun sleep(){

println("$name sedang tidur !")

Dengan begitu kelas Animal tidak dapat kita inisialisasikan menjadi


sebuah objek.

fun main(){

val animal = Animal("dicoding animal", 2.6, 1, true)

// Output: cannot create an instance of an abstract class

Ketika kita mencoba membuat objek dari kelas Animal, akan terdapat
eror berikut:

Cannot create an instance of an abstract class

Interfaces
Interfaces merupakan suatu konsep sifat umum yang nantinya
digunakan oleh suatu kelas agar dapat memiliki sifat tersebut.
Interface sangat mirip dengan abstract class, namun tanpa sebuah
properti deklarasi dan fungsi yang dideklarasikan tanpa isi. Tujuan dari
interface ini hanya untuk diimplementasikan oleh sebuah kelas. Kelas
yang mengimplementasikan sebuah interface diharuskan melakukan
override seluruh properti dan fungsi sekaligus mendefinisikan isi
fungsi yang terdapat pada interfaces-nya.

Cara pembuatan sebuah interface mirip dengan membuat kelas. Pada


umumnya penamaan sebuah interface dituliskan dengan awalan
huruf I kapital. Hal ini tidak diharuskan secara sintaks tapi ini
merupakan penerapan terbaik dalam penamaan sebuah interface.
Tujuannya agar dapat mudah membedakannya dengan kelas. Berikut
merupakan contoh pembuatan sebuah interface:

interface IFly {

fun fly()

Cara mengimplementasikan sebuah interface pada kelas, sama seperti


kita melakukan extends pada sebuah super atau parent class. Untuk
lebih jelasnya, mari kita buat sebuah kelas burung dengan
mengimplementasikan interface IFly:

class Bird : IFly {

Kita akan mendapati eror ketika selesai menuliskan kode tersebut.


Pesan eror tersebut mengatakan “class Bird is not abstract and does
not implement abstract member”. Maksud dari eror tersebut adalah
kita harus mengimplementasi sebuah abstract member yang pada
kasus ini adalah sebuah fungsi abstract yang terdapat pada IFly. Maka
untuk menghilangkan eror tersebut, kita harus
melakukan override fungsi yang terdapat pada IFly.

class Bird : IFly {


override fun fly() {

println("I flying without wings")

Untuk menambahkan sebuah properti pada interface, kita cukup


menuliskannya seperti pada kelas namun tanpa melakukan inisialisasi
nilai:

interface IFly {

fun fly()

val numberOfWings: Int

Sama seperti fungsi, kita juga diharuskan


melakukan override properti. Overriding properti bisa dilakukan pada
sebuah konstruktor kelas seperti berikut:

class Bird(override val numberOfWings: Int) : IFly {

override fun fly() {

if(numberOfWings > 0) println("Flying with $numberOfWings


wings")

else println("I'm Flying without wings")

Perbedaan Abstract Class dan Interface


Walaupun sekilas mirip karena sama sama dapat digunakan untuk
kontrak pewarisan dan tidak dapat diinisialisasi langsung menjadi
object (harus diturunkan dulu), abstract class dan interface memiliki
beberapa perbedaan. Untuk lebih jelasnya, perhatikan kode berikut ini.

abstract class Animal {

//default value not allowed

abstract val age: Int //must be overridden

//default value allowed

open val isEating = true //optional to be overridden

val isRespire = true //can not be overridden

interface IWalk {

//default value not allowed

val numberOfLeg: Int //must be overridden

fun walk() //must be overridden

interface IDrink {

class Camel : Animal(), IWalk, IDrink {

override val age: Int = 7 // this property must exist, try to remove it
override val isEating = true // this property optional, try to remove it

override val numberOfLeg = 2 // this property must exist, try to


remove it

override fun walk() { // this method must exist, try to remove it

println("Camel can walk")

fun main(){

val camel = Camel()

camel.walk()

Dari kode di atas, kita dapat menyimpulkan beberapa perbedaan


berikut ini.

Abstract Class Interface


Bisa berisi default value. Tidak bisa berisi default value.
Setiap member final secara default. Supaya bisa di-override, Setiap membernya abstract secara
gunakan keyword abstract (wajib) dan open (opsional). default dan harus di-override.
1 class hanya bisa extend satu abstract class, ditandai dengan (). 1 class bisa implement lebih dari satu
interface.
Digunakan jika tidak tahu implementasi sebagian member. Digunakan jika tidak tahu implementasi
keseluruhan member.

Extensions
Kotlin memungkinkan kita untuk menambahkan sebuah fungsi baru
pada sebuah kelas tanpa harus mewarisi kelas tersebut. Misalnya, jika
ingin menambahkan fungsi baru untuk kelas Int, kita akan
menuliskannya seperti berikut.

class NewInt : Int(){

fun printInt(){

println("value $this")

Kira-kira kenapa ketika kode dijalankan, ia akan gagal dikompilasi? Hal


itu karena kelas Int bersifat final sehingga tidak memungkinkan untuk
mewarisi kelas tersebut. Oleh karena itu, kita bisa melakukannya
dengan deklarasi khusus yang disebut dengan Extensions.

Kotlin mendukung 2 (dua) extension yang dapat digunakan,


yaitu Extension Functions dan Extension Properties. Jika extension
functions digunakan untuk menambahkan fungsi baru, extension
properties tentunya digunakan untuk menambahkan sebuah properti
baru.
Extension Functions
Untuk mendeklarasikan sebuah extension functions, kita perlu
menentukan terlebih dahulu receiver type, kemudian nama dari fungsi
tersebut yang mana keduanya dipisahkan oleh titik (.). Contohnya
seperti berikut:

fun Int.printInt() {

print("value $this")

Bisa kita perhatikan, kelas Int pada kode di atas digunakan


sebagai receiver type, sedangkan kata kunci this adalah receiver
type yang bertindak sebagai objeknya. Nilai dari objek tersebut bisa
digunakan di dalam extension yang sudah dibuat.

Untuk memanggil extension functions di atas, lakukan dengan cara


berikut.

fun main() {

10.printInt()

/*

output : value 10

*/

Selain itu, jika extension functions tersebut dapat mengembalikan nilai,


deklarasinya pun sama halnya seperti fungsi pada umumnya.
Contohnya seperti berikut,

fun main() {

println(10.plusThree())
}

fun Int.plusThree(): Int {

return this + 3

/*

output : 13

*/

Extension Properties
Seperti yang disebutkan di awal, Kotlin juga
mendukung extension untuk menambah sebuah properti baru pada
sebuah kelas tanpa harus menyentuh kode di dalam kelas tersebut.

Deklarasinya pun sama seperti extension functions. Kita terlebih


dahulu menentukan receiver type kemudian nama dari properti
tersebut. Contoh seperti berikut:

val Int.slice: Int

get() = this / 2

Untuk memanggil extension di atas, lakukan dengan cara berikut:

fun main() {

println(10.slice)

/*
output : 5

*/

Yang perlu diketahui, extension tidak benar-benar mengubah sebuah


kelas dengan menambahkan sebuah fungsi atau properti baru. Ini
karena extension memiliki hubungan langsung dengan kelas yang ingin
diperluas fungsionalitasnya. Oleh karena itu, extension properties
hanya bisa dideklarasikan dengan cara
menyediakan getter atau setter secara eksplisit.

Infix Function
Anda sudah mempelajari cara membuat sebuah function, mengelola,
hingga menggunakannya. Untuk memanggil sebuah function, Anda
melakukannya dengan memanggil nama function tersebut dan diakhiri
dengan kurung buka tutup. Namun, ternyata ada cara lain dalam
pemanggilan sebuah function. Anda bisa menggunakan infix function
untuk memanggil suatu fungsi dengan cara yang lebih ringkas dan
mirip dengan pemakaian operator matematika.

Contohnya Anda memiliki sebuah function untuk menambahkan dua


nilai angka seperti berikut.

fun Int.sum(value: Int): Int {

return this + value

Untuk memanggil function tersebut, Anda perlu menambahkan titik,


kemudian nama functionnya, dan memasukkan nilai yang dibutuhkan.

val result = 5.sum(3)

Berbeda jika Anda menambahkan keyword infix di awal function


tersebut.
infix fun Int.sum(value: Int): Int {

return this + value

Anda bisa memanggilnya secara langsung layaknya menuliskan


bilangan matematika.

val result = 5 sum 3 // Menggunakan Infix Function

Namun, ada beberapa syarat untuk menggunakan infix function.

1. Infix function harus merupakan sebuah member function atau


extension function.
2. Harus memiliki satu parameter saja.
3. Parameter tidak boleh berupa generic dan tidak memiliki nilai
default.
Perhatikan bahwa infix function harus selalu menerima parameter
yang ditentukan. Ketika memanggil method dengan notasi infix, Anda
bisa menggunakan this yang nantinya akan mereferensikan ke method
tersebut. Hal ini diperlukan untuk memastikan penguraian yang jelas.
class MyHero {

infix fun addHero(s: String) { /*...*/ }

fun build() {

this addHero "Superman" // Correct

addHero("Spidermen") // Correct

// addHero "Ironman" // Incorrect: the receiver must be specified

}
Nullable Receiver
Menariknya, kita bisa juga mendeklarasikan sebuah extension
dengan nullable receiver type. Alhasil, extension tersebut bisa dipanggil
pada objek yang bahkan nilainya null.

val Int?.slice: Int

get() = if (this == null) 0 else this.div(2)

If expression pada contoh di atas adalah untuk memeriksa


apakah receiver object-nya bernilai null. Jika tidak bernilai null,
maka receiver object tersebut akan secara otomatis di-casting menjadi
tipe non-null, sehingga kita bisa menggunakan nilainya.

Selain menggunakan if expression, kita juga bisa menggunakan elvis


operator. Misalnya seperti berikut:

val Int?.slice: Int

get() = this?.div(2) ?: 0

Untuk memanggilnya pun sama seperti extension properties


sebelumnya.

fun main() {

val value: Int? = null

println(value.slice)

/*

output : 0

*/
Lalu kapan kita membutuhkannya? Tentunya jika kita mempunyai
sebuah objek yang bernilai null. Saat kita tidak menetapkannya
dengan nullable receiver type, maka kita perlu memeriksa apakah objek
tersebut bernilai null atau tidak? Bisa juga dengan menggunakan
operator safe call setiap kali extension tersebut dipanggil. Contohnya
seperti berikut:

fun main() {

val value: Int? = null

val value1: Int? = null

println(value?.slice)

println(value1?.slice)

val Int.slice: Int

get() = this.div(2)

/*

output : null

null

*/

Kita juga bisa menentukan nilai dari receiver object jika bernilai null.
Sehingga kita tidak perlu lagi menggunakan operator safe call ketika
ingin memanggil extension tersebut.
fun main() {
val value: Int? = null

val value1: Int? = null

println(value.slice)

println(value1.slice)

val Int?.slice: Int

get() = this?.div(2) ?: 0

/*

output : 0

*/

Import dan Packages


Seluruh konten pada Kotlin, seperti kelas dan fungsi, dibungkus dalam
sebuah package. Package tersebut digunakan untuk mengelompokkan
kelas, fungsi dan variabel yang mempunyai kemiripan fungsionalitas.
Untuk menggunakan kelas, fungsi maupun variabel yang berada pada
suatu package, kita harus menuliskan secara lengkap
alamat package tersebut. Sebagai contoh kita akan menggunakan
kelas Random, maka kita harus menuliskan seperti ini:

val someInt = kotlin.random.Random(0).nextInt(1, 10)

\Kode tersebut menunjukkan bahwa kelas Random berada


pada package kotlin.random, tetapi apakah perlu menuliskan kode
sepanjang itu untuk menggunakan sebuah kelas? Tentu tidak, untuk
meminimalisir hal tersebut kita cukup mengimpor package
kelas Random. Dengan begitu kita tidak perlu menuliskan kode yang
panjang secara berulang.
Importing Package
Untuk mengimpor suatu package kelas, fungsi atau variabel, kita cukup
menuliskan keyword import kemudian dilanjutkan dengan alamat
spesifiknya seperti:

import packagename.ClassName

import packagename.functionName

import packagename.propertyName

Karena kelas Random berada pada package kotlin.random, maka


penulisannya menjadi seperti ini:

import kotlin.random.Random

Setelah kita impor kelas Random beserta alamat package-nya, kita


dapat menuliskan kelas Random secara langsung tanpa menulis
seluruh alamat package-nya. Tentunya hal ini akan membuat waktu
dalam menuliskan kode lebih efisien.

import kotlin.random.Random

val someInt = Random(0).nextInt(1, 10)

Biasanya terdapat banyak kelas, fungsi ataupun variabel dalam


sebuah package. Contohnya kita akan menggunakan beberapa fungsi
dan variabel matematika pada package kotlin.math seperti berikut:

import kotlin.math.PI

import kotlin.math.cos

import kotlin.math.sqrt

fun main(){
println(PI)

println(cos(120.0))

println(sqrt(9.0))

/*

Output:

3.141592653589793

0.8141809705265618

3.0

*/

Kita juga dapat mengganti nama sebuah kelas, fungsi atau variabel
yang kita import dengan menggunakan alias yang direpresentasikan
dengan kata kunci as.

import kotlin.math.PI

import kotlin.math.cos as cosinus

import kotlin.math.sqrt as akar

fun main(){

println(PI)

println(cosinus(120.0))

println(akar(9.0))

}
/*

Output:

3.141592653589793

0.8141809705265618

3.0

*/

Biasanya as digunakan ketika kita menggunakan sebuah kelas, fungsi,


maupun variabel yang memiliki nama yang sama namun
berbeda package-nya. Ini bertujuan untuk menghindari ambiguitas.

Seperti yang kita ketahui sebelumnya,


pada package kotlin.math terdapat banyak fungsi dan variabel yang
dapat kita gunakan. Kita bisa melihat pada completion
suggestion berikut:

Kita dapat mengimpor seluruh kelas, fungsi dan variabel yang berada
pada suatu package dengan menggunakan tanda * pada
akhir package tersebut.
import kotlin.math.*

fun main(){

println(PI)

println(cos(120.0))

println(sqrt(9.0))

/*

Output:

3.141592653589793

0.8141809705265618

3.0

*/

Membuat Package Baru


Seperti yang diketahui sebelumnya, package merupakan pembungkus
dari kelas (package-level class), fungsi (package-level function) atau
variabel (package-level variable) berfungsi serupa. Kita juga sudah
mengetahui cara mengimpor suatu kelas, fungsi atau variabel yang
terdapat pada sebuah package. Namun kita belum tahu
bagaimana package tersebut dibuat. Jadi pada pembahasan kali ini kita
akan mencoba bagaimana untuk membuat sebuah package pada
Kotlin.

Idealnya sebuah package pada Kotlin dituliskan dengan awalan nama


domain perusahaan yang dibalik. Contoh, com.dicoding. Kemudian
diikuti dengan nama package yang akan digunakan.

Untuk membuat sebuah package kita perlu membuat


folder package pada berkas proyek. Perhatikan Project Tool
Window yang terdapat pada IntelliJ Idea. Klik kanan pada
folder src kemudian arahkan pada menu New > package.
Setelah itu ketikkan nama package yang akan kita buat, misalnya
"com.dicoding.oop.utils".

Perlu diingat bahwa penamaan package selalu dituliskan


dengan flatcase, tanpa garis bawah dan dipisahkan dengan titik.

Dengan menekan tombol “OK”, kita berhasil membuat sebuah package


folder pada proyek aplikasi. Seperti inilah struktur proyek tersebut.
Selanjutnya, buatlah sebuah berkas di dalam package utils. Disini kita
menamai berkas tersebut dengan nama MyMath.kt. Bukalah berkas
tersebut dan perhatikan baris kode yang dihasilkan oleh IntelliJ Idea.
Seharusnya kita melihat baris kode berikut pada berkas MyMath.kt.
package com.dicoding.oop.utils

fun sayHello() = println("Hello From package com.dicoding.oop.utils")

Kita sudah membuat sebuah fungsi sayHello() pada package-level.


Untuk mengakses fungsi tersebut, kita dapat menuliskan secara
eksplisit alamat package. Buatlah sebuah berkas Kotlin dengan
nama Main.kt pada package com.dicoding.oop kemudian akses
fungsi sayHello() yang terdapat pada package com.dicoding.oop.utils
fun main(){

com.dicoding.oop.utils.sayHello()

/*
Output:

Hello From package com.dicoding.oop.utils

*/

Atau kita dapat menggunakan fungsi tersebut dengan


mengimpor package-level function tersebut.
package com.dicoding.oop

import com.dicoding.oop.utils.sayHello

fun main() {

sayHello()

/*

Output:

Hello From package com.dicoding.oop.utils

*/

Untuk dapat memahami tentang package lebih lanjut, mari kita buat
beberapa fungsi dan variabel pada package tersebut. Buka kembali
berkas MyMath.kt, tambahkan beberapa fungsi dan variabel yang akan
kita gunakan nantinya.
package com.dicoding.oop.utils

fun sayHello() = println("Hello From package utils")

const val PI = 3.1415926535 // package level variable


fun pow(number: Double, power: Double) : Double {

var result = 1.0

var counter = power

while (counter > 0) {

result *= number

counter--

return result

fun factorial(number: Double) : Double {

var result = 1.0

var counter = 1.0

while (counter <= number) {

result *= counter

counter++

return result

fun areaOfCircle(radius: Double) : Double {

return PI * 2 * radius

Panggil beberapa fungsi dan variabel yang sudah ditambahkan


pada MyMath.kt.
package com.dicoding.oop
import com.dicoding.oop.utils.PI

import com.dicoding.oop.utils.factorial

import com.dicoding.oop.utils.pow

import com.dicoding.oop.utils.sayHello

fun main() {

sayHello()

println(factorial(4.0))

println(pow(3.0, 2.0))

println(PI)

/*

output:

Hello From package com.dicoding.oop.utils

24.0

9.0

3.1415926535

*/

Pada awal kode terlihat saat kita menggunakan suatu fungsi atau
variabel yang berada pada package tertentu, kita perlu melakukan
impor pada setiap fungsi atau variabelnya. Namun, jika kita
menggunakan seluruh fungsi atau variabel dalam package tertentu kita
bisa menggunakan tanda bintang (*) untuk melakukan impor pada
seluruh fungsi dan variabel di package tersebut. Perhatikan kode
berikut.
package com.dicoding.oop

import com.dicoding.oop.utils.*
fun main() {

sayHello()

println(factorial(4.0))

println(pow(3.0, 2.0))

println(PI)

println(areaOfCircle(13.0))

/*

output:

Hello From package com.dicoding.oop.utils

24.0

9.0

3.1415926535

81.681408991

*/

Dengan memanggil fungsi areaOfCircle(), kita menggunakan seluruh


fungsi dan variabel yang berada pada
package com.dicoding.oop.utils sehingga import package cukup
dilakukan dengan tanda bintang (*).

Exception
Kode yang baik yaitu kode yang terhindar dari segala bentuk kejadian
dengan efek buruk pada aplikasi kita. Kejadian tersebut pada
programming disebut Exception. Hal terburuk yang disebabkan
oleh exception ini adalah dapat terhentinya aplikasi ketika dijalankan.
Hal seperti ini seharusnya kita hindari. Nah karena itu kita harus
mengetahui cara menangani suatu exception (Exception Handling) pada
sub-modul selanjutnya.

Apa itu Exception?


Exception adalah event (kejadian) yang dapat mengacaukan jalannya
suatu program. Pada Kotlin semua exception bersifat Unchecked, yang
artinya exception terjadi karena kesalahan pada kode kita. Berikut ini
beberapa contoh Unchecked Exception yang sering mengganggu
jalannya program kita:

ArithmeticException

 NumberFormatException
 NullPointerException
ArithmeticException merupakan exception yang terjadi karena kita
membagi suatu bilangan dengan nilai nol. Berikut merupakan contoh
kode yang dapat membangkitkan ArithmeticException.
fun main() {

val someValue = 6

println(someValue / 0)

/*

output:

Exception in thread "main" java.lang.ArithmeticException: / by zero

*/

NumberFormatException disebabkan karena terjadi kesalahan dalam


format angka. Sebagai contoh, kita akan mengubah sebuah nilai String
menjadi Integer tetapi nilai String yang akan kita ubah tidak memiliki
format angka yang benar, sehingga dapat
membangkitkan NumberFormatException. Berikut contoh kodenya:
fun main() {

val someStringValue = "18.0"


println(someStringValue.toInt())

/*

output:

Exception in thread "main" java.lang.NumberFormatException: For input string: "18.0"

*/

Dan yang terakhir adalah NullPointerException atau NPE. Walaupun


Kotlin memiliki operator Null Safety, NPE tetap bisa saja terjadi. NPE
terjadi karena sebuah variabel atau objek memiliki nilai null, padahal
seharusnya objek atau variabel tersebut tidak boleh null. Berikut
contoh kasus yang dapat menyebabkan NullPointerException:
fun main() {

val someNullValue: String? = null

val someMustNotNullValue: String = someNullValue!!

println(someMustNotNullValue)

/*

output:

Exception in thread "main" kotlin.NullPointerException at MainKt.main(Main.kt:3)

*/

Exception Handling
Exception handling dapat diterapkan dengan beberapa cara. Di
antaranya adalah dengan menggunakan try-catch, try-catch-finally,
dan multiple catch. Mari kita pelajari ketiga cara tersebut.

try-catch
Salah satu cara untuk menangani suatu exception adalah
menggunakan try-catch. Kode yang dapat membangkitkan
suatu exception disimpan dalam blok try, dan jika exception tersebut
terjadi, maka blok catch akan terpanggil. Berikut cara penulisan try-
catch pada Kotlin:
try {

// Block try, menyimpan kode yang membangkitkan exception

} catch (e: SomeException) {

// Block catch akan terpanggil ketika exception bangkit.

Dengan menuliskan kode dalam blok try, kode kita menjadi terproteksi
dari exception. Jika terjadi exception maka program tidak akan terhenti
atau crash, namun akan dilempar menuju blok catch. Di sana kita
dapat menuliskan sebuah kode alternatif untuk menampilkan pesan
eror atau yang lainnya.
fun main() {

val someNullValue: String? = null

lateinit var someMustNotNullValue: String

try {

someMustNotNullValue = someNullValue!!

println(someMustNotNullValue)

} catch (e: Exception) {

someMustNotNullValue = "Nilai String Null"

println(someMustNotNullValue)

/*

output:

Nilai String Null

*/
try-catch-finally
Selain terdapat blok try dan catch, ada juga blok finally. Hanya saja
blok ini bersifat opsional. finally akan dieksekusi setelah program
keluar dari blok try ataupun catch. Bahkan finally juga tereksekusi
ketika terjadi exception yang tidak terduga. Exception tidak terduga
terjadi ketika kita
menggunakan NullPointerException pada catch namun exception yan
g terjadi adalah NumberFormatException.

Sebagai contoh, mari kita ubah kode yang sebelumnya dengan


menerapkan finally:
fun main() {

val someNullValue: String? = null

lateinit var someMustNotNullValue: String

try {

someMustNotNullValue = someNullValue!!

} catch (e: Exception) {

someMustNotNullValue = "Nilai String Null"

} finally {

println(someMustNotNullValue)

/*

output:

Nilai String Null

*/

Dengan menerapkan finally, fungsi println() cukup dituliskan pada


blok finally.
Multiple Catch
Dari kode yang kita coba sebelumnya, kita
menggunakan exception untuk menangani semua tipe exception yang
terjadi. Baik itu ketika
terjadi NullPointerException atau NumberFormatException.
Sebenarnya pada catch kita dapat secara spesifik memilih tipe
exception apa yang ingin ditangani. Multiple catch memungkinkan
untuk penanganan exception dapat ditangani lebih dari satu
tipe exception. Hal ini sangat berguna ketika kita ingin menangani
setiap tipe exception dengan perlakuan yang berbeda. Berikut contoh
struktur kode dengan menerapkan multiple catch:
try{

// Block try, menyimpan kode yang membangkitkan exception

} catch (e: NullPointerException) {

// Block catch akan terpanggil ketika terjadi NullPointerException.

} catch (e: NumberFormatException) {

// Block catch akan terpanggil ketika terjadi NumberFormatException.

} catch (e: Exception) {

// Block catch akan terpanggil ketika terjadi Exception selain keduanya.

finally {

// Block finally akan terpanggil setelah keluar dari block try atau catch

Dari struktur kode di atas, kita dapat melihat terdapat 3 (tiga)


blok catch. Block catch yang pertama menggunakan
parameter NullPointerException, sehingga jika
terjadi NullPointerException maka blok catch tersebut akan
dieksekusi. Yang kedua block catch dengan
parameter NumberFormatException, sehingga jika
terjadi NumberFormatException maka blok tersebut yang akan
dieksekusi. Dan yang terakhir blok catch dengan
parameter Exception, blok ini akan menangani seluruh exception yang
terjadi kecuali untuk dua exception yang telah ditentukan pada blok
sebelumnya.
Mari kita coba terapkan contoh kode yang sebelumnya kita buat
dengan menggunakan multiple catch.
import kotlin.NumberFormatException

fun main() {

val someStringValue: String? = null

var someIntValue: Int = 0

try {

someIntValue = someStringValue!!.toInt()

} catch (e: NullPointerException) {

someIntValue = 0

} catch (e: NumberFormatException) {

someIntValue = -1

} finally {

when(someIntValue){

0 -> println("Catch block NullPointerException terpanggil !")

-1 -> println("Catch block NumberFormatException terpanggil !")

else -> println(someIntValue)

/*

output:

Catch block NullPointerException terpanggil!

*/

Output kode di atas menjelaskan bahwa blok catch dengan


parameter NullPointerException terpanggil. Sebabnya, pada
variabel someStringValue kita menetapkan null sebagai nilainya.
Berbeda ketika kita menginisialisasi nilai someStringValue dengan nilai
“12.0” maka exception yang akan terjadi
adalah NumberFormatException dengan begitu blok catch kedua
yang akan terpanggil dan akan menghasilkan output sebagai berikut:
Catch block NumberFormatException terpanggil!

Namun jika kedua exception tersebut tidak terjadi, dalam arti


nilai someStringValue berhasil diubah dalam bentuk Integer, maka
output yang dihasilkan adalah nilai dari Integernya tersebut.
Contohnya, saat nilai someStringValue diinisialisasi dengan nilai “12.”
Berikut ini hasilnya. :

12

Rangkuman dari Kotlin Object-Oriented Programming


Okay, kita sudah selesai belajar dan mengetahui mengenai paradigma
Object-Oriented pada Kotlin. Untuk me-refresh apa yang sudah kita
pelajari, mari kita merangkum beberapa hal penting mengenai
paradigma ini.

 Object-Oriented Programming masih menjadi salah satu


paradigma atau teknik pemrograman yang banyak digunakan
dalam pengembangan aplikasi.
 Gambaran umum dari Object-Oriented Programming adalah
sebuah blueprint, di mana blueprint ini adalah
sebuah Class (kelas).
 Pada Object-Oriented Programming terdapat beberapa
komponen penting
yaitu Object, Class, Attribute dan Behaviour.
 Object atau Objek merupakan hasil realisasi dari
sebuah blueprint atau class yang tentunya memiliki method dan
juga properti sama seperti blueprint-nya. Salah satu contoh
Object yang sering kita pakai adalah nilai primitif pada Kotlin,
yaitu String, Integer, Char dan Boolean. Kegunaan dari Objek
sendiri adalah untuk mengakses berbagai properti dan fungsi
pada kelas.
 Class merupakan sebuah blueprint. Setiap kelas memiliki atribut
dan behaviour. Dalam Kotlin, attributes lebih sering disebut
dengan properties, sedangkan behaviour sering disebut functions.
Berikut penjelasan singkat dari setiap komponen:

o Class: Merupakan sebuah blueprint yang terdapat properti


dan fungsi di dalamnya.
o Properties: Karakteristik dari sebuah kelas, memiliki tipe
data.
o Method: Kemampuan atau aksi dari sebuah kelas.
 Lateinit merupakan keyword yang ditambahkan sebelum
variabel untuk membuat proses inisialisasi bisa ditunda.
Sedangkan by lazy merupakan property delagation yang
digunakan untuk menunda inisialisasi sampai property benar-
benar digunakan.
 Teknik membuat sebuah kelas yang memang bertugas untuk
mengatur atau mengelola fungsi getter dan setter untuk sebuah
properti kelas pada Kotlin dinamakan Delegate.
 Konstruktor merupakan fungsi spesial yang digunakan untuk
menginisialisasi properti yang terdapat pada sebuah kelas.
 Terdapat 3 (tiga) tipe konstruktor pada Kotlin, yaitu primary
constructor, secondary constructor dan default constructor.

o Primary Constructor

 Seperti namanya, jika kita akan membuat suatu objek


dari sebuah kelas dan kelas tersebut
memiliki constructor di dalamnya, maka konstruktor
tersebut adalah primary constructor dan diharuskan
untuk mengirim nilai sesuai properti yang
dibutuhkan.
 Primary Constructor juga dapat memiliki nilai default,
dengan begitu jika kita tidak menetapkan nilai untuk
parameter tersebut maka properti tersebut akan
memiliki nilai default.
 Kotlin menyediakan blok init yang memungkinkan kita
untuk menuliskan properti di dalam body class ketika
kita menggunakan primary constructor.
o Secondary Constructor
 Secondary constructor digunakan ketika kita ingin
menginisialisasi sebuah kelas dengan cara yang lain.

 Dapat memiliki lebih dari satu secondary constructor.


o Default Constructor

 Kotlin secara otomatis membuat sebuah default


constructor pada kelas jika kita tidak membuat sebuah
konstruktor secara manual.
 Visibility Modifier adalah hak akses pada Kotlin. Dengan
menentukan hak akses tersebut, kita dapat membatasi akses
data pada sebuah kelas. Berikut macam-macam hak akses dan
penjelasan singkatnya yang dapat digunakan pada Kotlin:
o Public: Hak akses yang cakupannya paling luas. Anggota
yang diberi modifier ini dapat diakses dari manapun.
o Private: Hak akses yang cakupannya paling terbatas.
Anggota yang menerapkannya hanya dapat diakses
pada scope yang sama.
o Protected: Hak akses yang cakupannya terbatas pada
hirarki kelas. Anggota hanya dapat diakses pada kelas
turunannya atau kelas itu sendiri.
o Internal: Hak akses yang cakupannya terbatas pada satu
modul. Anggota yang menggunakannya tidak dapat diakses
diluar dari modulnya tersebut.
 Pada Object-Oriented Programming
terdapat Inheritance/Pewarisan. Inheritance dapat mencegah
kita melakukan perulangan kode dengan cara mengelompokkan
properti dan fungsi yang sama. Pada Inheritance,
terdapat parent class dan juga child class.
 Pada Kotlin menggunakan dua atau lebih fungsi dengan nama
yang sama disebut dengan overloading. Overloading dapat
dilakukan selama fungsi itu memiliki parameter yang berbeda.
 Abstract Class merupakan gambaran umum dari sebuah kelas.
Abstract Class tidak dapat direalisasikan dalam sebuah objek.
 Interfaces merupakan suatu konsep sifat umum yang nantinya
digunakan oleh suatu kelas agar dapat memiliki sifat tersebut.
 Kotlin mendukung 2 (dua) extension yang dapat digunakan,
yaitu Extension Functions dan Extension Properties. Jika
extension functions digunakan untuk menambahkan fungsi baru,
extension properties tentunya digunakan untuk menambahkan
sebuah properti baru tanpa harus membuat sebuah kelas yang
mewarisi kelas tersebut.
 Seluruh konten pada Kotlin, seperti kelas dan fungsi, dibungkus
dalam sebuah package. Package tersebut digunakan untuk
mengelompokkan kelas, fungsi dan variabel yang mempunyai
kemiripan fungsionalitas.
 Exception adalah event (kejadian) yang dapat mengacaukan
jalannya suatu program. Pada Kotlin
semua exception bersifat Unchecked, yang
artinya exception terjadi karena kesalahan pada kode kita. Kode
yang baik yaitu kode yang terhindar dari segala bentuk kejadian
dengan efek buruk pada aplikasi kita. Kejadian tersebut pada
programming disebut Exception. Hal seperti ini seharusnya
dihindari. Oleh karena itu kita harus mengetahui cara menangani
suatu exception (Exception Handling).
 Berikut ini beberapa contoh Unchecked Exception yang sering
mengganggu jalannya program kita:

o ArithmeticException

Merupakan exception yang terjadi karena


kita membagi suatu bilangan dengan nilai nol.
o NumberFormatException

 Disebabkan karena terjadi kesalahan


dalam format angka.
o NullPointerException

 Terjadi karena sebuah variabel atau objek memiliki


nilai null, padahal seharusnya objek atau variabel
tersebut tidak boleh null.
 Exception Handling dapat diterapkan dengan beberapa cara. Di
antaranya adalah dengan menggunakan try-catch, try-catch-
finally, dan multiple catch.

Anda mungkin juga menyukai