news

Sabtu, 13 Juni 2020

Belajar Constructor di Kotlin Lengkap



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 3 (tiga) tipe konstruktor pada Kotlin, yaitu primary constructorsecondary constructor dan default constructor. Yuk kita coba mempelajarinya bersama.

Primary Constructor

Seperti namanya, jika kita akan membuat suatu objek dari sebuah kelas dan kelas tersebut memiliki primary constructor di dalamnya, maka kita diharuskan 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:

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



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

  1. fun main(){

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

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

  4. }

  5.  

  6. /*

  7. output:

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

  9. */



Perhatikan kode di atas. Karena kelas Animal memiliki primary constructor, maka saat membuat objeknya kita perlu mengirimkan beberapa nilai yaitu nameweightage dan isMammal.
Primary constructor juga dapat memiliki nilai default, dengan begitu jika kita tidak menetapkan nilai untuk parameter tersebut maka properti tersebut akan memiliki nilai default
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:

  1. 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.

  1. fun main(){

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

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

  4. }

  5.  

  6. /*

  7.  output:

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

  9. */



Hasil dari kode tersebut memperlihatkan bahwa properti age dan isMammal memiliki nilai default. Sekali lagi, properti tersebut bersifat opsional, dengan begitu 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.

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



Kotlin menyediakan blok init yang memungkinkan kita untuk menuliskan properti didalam 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:

  1. class Animal(pName: String, pWeight: Double, pAge: Int, pIsMammal: Boolean){

  2.     val name: String

  3.     val weight: Double

  4.     val age: Int

  5.     val isMammal: Boolean

  6.  

  7.     init {

  8.         weight = if(pWeight < 0) 0.1 else pWeight

  9.         age = if(pAge < 0) 0 else pAge

  10.         name = pName

  11.         isMammal = pIsMammal

  12.     }

  13. }



Primary constructor dan init harus saling terhubung. Fungsi init dijalankan ketika suatu objek dibuat dengan menggunakan primary constructor. Mari kita coba untuk membuatnya.

  1. fun main() {

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

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

  4. }

  5.  

  6. /*

  7. output:

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

  9. */



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.

  1. class Animal(name: String, weight: Double, age: Int, isMammal: Boolean) {

  2.     val name: String

  3.     val weight: Double

  4.     val age: Int

  5.     val isMammal: Boolean

  6.  

  7.     init {

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

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

  10.         this.name = name

  11.         this.isMammal = isMammal

  12.     }

  13. }



Kata kunci this tersebut merujuk kepada suatu kelas dimana jika kita menggunakannya diikuti dengan nama properti maka kita menunjuk pada properti yang terdapat pada kelas tersebut. 
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:
  1. class Animal(name: String, weight: Double, age: Int) {
  2.     val name: String
  3.     val weight: Double
  4.     val age: Int
  5.     var isMammal: Boolean
  6.  
  7.     init {
  8.         this.weight = if(weight < 0) 0.1 else weight
  9.         this.age = if(age < 0) 0  else age
  10.         this.name = name
  11.         this.isMammal = false
  12.     }
  13.  
  14.     constructor(name: String, weight: Double, age: Int, isMammal: Boolean) : this(name, weight, age) {
  15.         this.isMammal = isMammal
  16.     }
  17. }
  18.  
  19. fun main() {
  20.     val dicodingCat = Animal("Dicoding Miaw", 2.5, 2, true)
  21.     println("Nama: ${dicodingCat.name}, Berat: ${dicodingCat.weight}, Umur: ${dicodingCat.age}, mamalia: ${dicodingCat.isMammal}")
  22.  
  23.     val dicodingBird = Animal("Dicoding tweet", 0.5, 1)
  24.     println("Nama: ${dicodingBird.name}, Berat: ${dicodingBird.weight}, Umur: ${dicodingBird.age}, mamalia: ${dicodingBird.isMammal}")
  25. }
  26.  
  27. /*
  28. output:
  29.     Nama: Dicoding Miaw, Berat: 2.5, Umur: 2, mamalia: true
  30.     Nama: Dicoding tweet, Berat: 0.5, Umur: 1, mamalia: false
  31. */

Dengan begitu, objek Animal dapat diinisialisasi dengan secondary constructor ketika nilai nameweightage 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:

  1. class Animal{

  2.     val name: String = "Dicoding Miaw"

  3.     val weight: Double = 4.2

  4.     val age: Int = 2

  5.     val isMammal: Boolean = true

  6. }

  7.  

  8. fun main(){

  9.     val dicodingCat = Animal()

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

  11. }

  12.  

  13. /*

  14. output:

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

  16. */


Ketika kita membuat sebuah objek, default konstruktor akan dipanggil. Konstruktor tersebut akan menginisialisasi properti yang terdapat pada kelas dengan nilai default