Kotlin From Scratch: Kelas dan Objek
Indonesian (Bahasa Indonesia) translation by Imam Firmansyah (you can also view the original English article)
Kotlin adalah bahasa pemrograman modern yang mengkompilasi ke bytecode Java. Bahasa pemrograman ini gratis dan open source, dan menjanjikan untuk membuat coding untuk Android semakin menyenangkan.
Pada artikel sebelumnya, Anda telah belajar penggunaan fungsi lanjutan, seperti extension functions, closures, higher-order functions, dan inline functions di Kotlin.
Dalam postingan ini Anda akan mendapatkan pengantar pemrograman berorientasi obyek di Kotlin dengan mempelajari kelas: konstruktor dan properti, casting, dan fitur kelas lanjutan yang Kotlin mudahkan.
1. Class
Kelas adalah unit program yang menggabungkan fungsi dan data untuk melakukan beberapa tugas terkait. Kami mendeklarasikan sebuah kelas di Kotlin dengan menggunakan keyword class — sama dengan Java.
1 |
class Book |
Kode sebelumnya adalah deklarasi kelas yang paling sederhana-kita baru saja membuat sebuah kelas kosong yang bernama Book. Kita masih bisa menginisiasi kelas ini meski tidak mmemiliki isi menggunakan konstruktor defaultnya.
1 |
val book = Book() |
Seperti yang bisa Anda amati pada kode di atas, kami tidak menggunakan keyword new untuk menginisiasi kelas ini-seperti biasa dalam bahasa pemrograman lainnya. new Bukan kata kunci di Kotlin. Hal ini membuat source code kita ringkas saat membuat instance kelas. Namun perlu disadari bahwa inisiasi kelas Kotlin di Java akan membutuhkan keyword new.
1 |
// In a Java file
|
2 |
Book book = new Book() |
Konstruktor Kelas dan Properti
Mari kita lihat bagaimana menambahkan konstruktor dan properti ke kelas kita. Tapi pertama, mari kita lihat kelas di Java:
1 |
/* Java */
|
2 |
public class Book { |
3 |
private String title; |
4 |
private Long isbn; |
5 |
public Book(String title, Long isbn) { |
6 |
this.title = title; |
7 |
this.isbn = isbn; |
8 |
}
|
9 |
public String getTitle() { |
10 |
return title; |
11 |
}
|
12 |
public void setTitle(String title) { |
13 |
this.title = title; |
14 |
}
|
15 |
public Long getIsbn() { |
16 |
return isbn; |
17 |
}
|
18 |
public void setIsbn(Long isbn) { |
19 |
this.isbn = isbn; |
20 |
}
|
21 |
}
|
Lihat pada model kelas Book di atas, kita memiliki:
- dua variabel:
titledanisbn - sebuah konstruktor
- getters dan setters untuk kedua variabel (untungnya, IntelliJ IDEA dapat membantu kita menghasilkan metode ini)
Sekarang mari kita lihat bagaimana kita bisa menulis kode sebelumnya di Kotlin sebagai gantinya:
1 |
/* Kotlin */
|
2 |
class Book { |
3 |
var title: String |
4 |
var isbn: Long |
5 |
|
6 |
constructor(title: String, isbn: Long) { |
7 |
this.title = title |
8 |
this.isbn = isbn |
9 |
}
|
10 |
}
|
Kelas yang cukup rapi! Kami sekarang telah mengurangi jumlah baris kode dari 20 menjadi hanya 9. Fungsi constructor() memanggil konstruktor sekunder in Kotlin. Konstruktor ini sama dengan konstruktor Java yang kita panggil saat menginisiasi sebuah kelas.
Di Kotlin, tidak ada konsep tentang variabel yang mungkin Anda kenal; Sebagai gantinya, ia menggunakan konsep "properti". Sebagai contoh, kita memiliki dua properti yang bisa dibaca (baca dan tulis) yang dideklarasikan dengan var keyword: title dan isbn di dalam class Book. (Jika Anda memerlukan penjelasan pada variabel di Kotlin, silakan kunjungi posting pertama di seri ini: Variables, Basic Types, and Arrays).
Hal yang menakjubkan adalah bahwa getter dan setter untuk properti ini dibuat secara otomatis untuk kita oleh kompiler Kotlin. Perhatikan bahwa kami tidak menentukan pengubah visibilitas terhadap properti ini-jadi secara default, bersifat publik. Dengan kata lain, bisa diakses dari mana saja.
Mari kita lihat versi lain dari kelas yang sama di Kotlin:
1 |
class Book constructor(title: String, isbn: Long) { |
2 |
var title: String |
3 |
var isbn: Long |
4 |
|
5 |
init { |
6 |
this.title = title |
7 |
this.isbn = isbn |
8 |
}
|
9 |
}
|
Dalam kode ini, kami telah menghapus konstruktor sekunder. Sebagai gantinya, kami mendeklarasikan sebuah konstruktor di header kelas yang disebut konstruktor utama. konstruktor utama tidak memiliki tempat untuk meletakkan blok kode, jadi kita memanfaatkan modifier init untuk menginisialisasi parameter yang masuk dari konstruktor utama. Perhatikan bahwa blok kode init dijalankan segera saat instance kelas dibuat.
Seperti yang bisa anda lihat, kode kita masih memiliki banyak boilerplate. Mari kita masuk ke penjelasan lebih jauh:
1 |
class Book constructor(var title: String, var isbn: Long) |
Kelas Book sekarang hanya satu baris kode! Perhatikan bahwa dalam daftar parameter konstruktor utama, kami mendefinisikan dengan properti mutable: title dan isbn langsung di dalam konstruktor utama dengan keyword var.
Kita juga bisa menambahkan nilai default ke salah satu properti kelas tepat di dalam constructor.
1 |
class Book constructor(var title: String = "default value", var isbn: Long) |
Sebenarnya, kita juga bisa menghilangkan keyword constructor, tapi hanya jika tidak memiliki modifier visibilitas:(public, private, atau protected) dan lainnya.
1 |
class Book (var title: String = "default value", var isbn: Long) |
Kelas yang sangat rapi, harus saya katakan!
Kita sekarang bisa membuat instance kelas seperti ini:
1 |
val book = Book("A Song of Ice and Fire", 9780007477159) |
2 |
val book2 = Book(1234) // uses the title property's default value |
Mengakses dan Mengatur Properti
Di Kotlin, kita bisa mendapatkan properti dengan objek kelas book, diikuti dengan titik ., lalu nama properti title. cara singkat untuk mengakses properti ini disebut property access syntax. Dengan kata lain, kita tidak perlu memanggil metode pengambil properti untuk mengakses atau memanggil setter untuk mengatur properti di Kotlin - seperti yang kita lakukan di Java.
1 |
println(book.title) // "A Song of Ice and Fire" |
Karena properti isbn dideklarasikan dengan kata keyword var (read-write), kita juga bisa mengubah nilai properti menggunakan operator =.
1 |
book.isbn = 1234 |
2 |
println(book.isbn) // 1234 |
Mari lihat contoh lain:
1 |
class Book ( |
2 |
var title: String, |
3 |
val isbn: Long |
4 |
)
|
5 |
|
6 |
val book = Book("A Song of Ice and Fire", 9780007477159) |
7 |
book.isbn = 1234 // error: read-only property |
8 |
book.title = "Things Fall Apart" // reassigned title with value |
Disini kita mengubah parameter isbn menjadi konstan (read-only) dengan menggunakan keyword val. Kita menginisiasi instance kelas book dan menentukan ulang properti title bernilai "Things Fall Apart". Perhatikan bahwa ketika kita mencoba untuk menentukan ulang nilai properti isbn menjadi 1234, kompilator merespon. Hal ini karena properti tersebut tidak dapat diubah, telah ditentukan dengan keyword val.
Interoperabilitas Java
Sadarilah bahwa mendeklarasikan parameter dengan modifier var di dalam konstruktor utama, kompiler Kotlin (di balik layar) telah membantu kami menghasilkan kedua aksesor properti: getter dan setter. Jika Anda menggunakan val, hanya akan menghasilkan getter.
1 |
/* Kotlin */
|
2 |
class Book ( |
3 |
var title: String, |
4 |
val isbn: Long |
5 |
)
|
Ini berarti bahwa pemanggil Java hanya bisa mendapatkan atau mengatur variabel properti dengan memanggil metode setter atau getter properti masing-masing. Ingat, ini tergantung pada modifier yang digunakan untuk menentukan properti Kotlin: var atau val.
1 |
/* Java */
|
2 |
Book book = new Book("A Song of Ice and Fire", 9780385474542) |
3 |
println(book.getTitle()) // "A Song of Ice and Fire" |
4 |
book.setTitle("Things Fall Apart") // sets new value |
5 |
println(book.getTitle()) // "Things Fall Apart" |
6 |
|
7 |
book.getIsbn() // 9780385474542 |
8 |
book.setIsbn(4545454) // won't compile |
Custom Getters dan Setters
Pada bagian ini, saya akan menunjukkan cara membuat pengakses kustom (getter dan setter) untuk properti di Kotlin jika Anda mau. Membuat setter kustom dapat berguna jika Anda ingin memvalidasi atau memverifikasi nilai sebelum diset ke properti kelas. Dan pengambil properti kustom bisa bermanfaat bila Anda ingin mengubah atau memodifikasi nilai yang harus dikembalikan.
Membuat Custom Setter
Karena kita ingin membuat getter atau setter kita sendiri untuk properti, kita harus mendefinisikan properti itu di kelas, bukan di header konstruktor.
1 |
class Book (val isbn: Long) { |
2 |
var title = "default value" |
3 |
}
|
Inilah sebabnya mengapa kami memindahkan mutable (read-write) properti title ke dalam isi kelas dan memberinya nilai default (atau tidak akan dikompilasi).
1 |
class Book (val isbn: Long) { |
2 |
var title = "default value" |
3 |
set(value) { |
4 |
if (!value.isNotEmpty()) { |
5 |
throw IllegalArgumentException("Title must not be empty") |
6 |
}
|
7 |
field = value |
8 |
}
|
9 |
}
|
Anda dapat lihat bahwa kami mendefinisikan metode setter kami sendiri set(value) untuk title Tepat di bawah definisi properti-perhatikan bahwa Anda tidak dapat memodifikasi ini. Metode set() karena ini adalah apa yang diinginkan compiler sebagai fungsi setter pada properti kustom.
parameter value melewatkan metode set mewakili nilai sebenarnya yang diberikan ke properti oleh pengguna-Anda dapat mengubah nama parameter jika Anda mau, tapi value lebih disarankan. Kita memvalidasi value dengan memeriksa apakah nilainya kosong Jika kosong, hentikan eksekusi dan lakukan pengecualian; Jika tidak, tetapkan kembali nilainya menjadi variabel spesial field.
variabel spesial field di dalam metode set adalah alias untuk field backing properti-field backing hanyalah variabel yang digunakan oleh properti saat Anda ingin memodifikasi atau menggunakan data variabel tersebut. Tidak seperti value, Anda tidak bisa merubah nama variabel spesial ini (field) .
Membuat Custom Getter
Sangat mudah untuk membuat getter kustom untuk properti di Kotlin.
1 |
class Book (val isbn: Long) { |
2 |
var title = "default value" |
3 |
//... set method
|
4 |
get() { |
5 |
return field.toUpperCase() |
6 |
}
|
7 |
}
|
Di dalam metode get, kami hanya mengembalikan nilai yang dimodifikasi field — Dalam hal ini, Kami mengembalikan judul buku itu dalam bentuk huruf besar.
1 |
val book = Book(9780007477159) |
2 |
book.title = "A Song of Ice and Fire" |
3 |
println(book.title) // "A SONG OF ICE AND FIRE" |
4 |
println(book.isbn) // 9780007477159 |
Perhatikan bahwa setiap kali kita menetapkan nilai ke properti title, metode set block dijalankan - hal yang sama berlaku untuk metode get setiap kali kita menerima nilai itu.
Jika Anda ingin belajar tentang member function untuk kelas Kotlin (jenis fungsi yang didefinisikan di dalam kelas, objek, atau antarmuka), kunjungi Lebih Menyenangkan dengan Function pada artikel berikut.
Mengenal Lebih Jauh Konstruktor
Seperti yang telah saya bahas sebelumnya, kita memiliki dua jenis konstruktor di Kotlin: primer dan sekunder. Kami bisa menggabungkan keduanya dalam satu kelas - seperti yang dapat Anda lihat pada contoh di bawah ini:
1 |
class Car(val name: String, val plateNo: String) { |
2 |
var new: Boolean = true |
3 |
|
4 |
constructor(name: String, plateNo: String, new: Boolean) : this(name, plateNo) { |
5 |
this.new = new |
6 |
}
|
7 |
}
|
Perhatikan bahwa kita tidak dapat mendeklarasikan properti di dalam konstruktor sekunder, seperti yang kita lakukan untuk konstruktor utama. Jika kita ingin melakukan ini, kita harus mendeklarasikannya di dalam isi kelas dan kemudian menginisialisasinya di konstruktor sekunder.
Pada kode di atas, kita tetapkan nilai default dari properti new untuk kelas Car (ingat, new bukan kata kunci di Kotlin) - kita kemudian bisa menggunakan konstruktor sekunder untuk mengubahnya jika kita mau. Di Kotlin, setiap konstruktor sekunder harus memanggil konstruktor utama, atau memanggil konstruktor sekunder lain yang memanggil konstruktor utama - kita menggunakan keywoard this untuk melakukan itu.
Perhatikan juga bahwa kita dapat memiliki beberapa konstruktor sekunder di dalam kelas.
1 |
class Car(val name: String, val plateNo: String) { |
2 |
var new: Boolean? = null |
3 |
var colour: String = "" |
4 |
|
5 |
constructor(name: String, plateNo: String, new: Boolean) : this(name, plateNo) { |
6 |
this.new = new |
7 |
}
|
8 |
|
9 |
constructor(name: String, plateNo: String, new: Boolean, colour: String ) : |
10 |
this(name, plateNo, new) { |
11 |
this.colour = colour |
12 |
}
|
13 |
}
|
Jika sebuah kelas extend sebuah super class, maka kita bisa menggunakan keyword super (sama dengan Java) untuk memanggil konstruktor superclass (kita akan membahas pewarisan di Kotlin pada posting berikutnya).
1 |
// directly calls primary constructor
|
2 |
val car1 = Car("Peugeot 504", "XYZ234") |
3 |
// directly calls 1st sec. constructor
|
4 |
val car2 = Car("Peugeot 504", "XYZ234", false) |
5 |
// directly calls last sec. constructor
|
6 |
val car3 = Car("Peugeot 504", "XYZ234", false, "grey") |
Seperti yang saya katakan sebelumnya, agar kita secara eksplisit menyertakan modifier visibilitas ke konstruktor di kelas, kita harus menyertakan keyword constructor secara default, konstruktor bersifat publik.
1 |
class Car private constructor(val name: String, val plateNo: String) { |
2 |
//...
|
Di sini, kita membuat konstruktor privae - ini berarti bahwa pengguna tidak dapat memberi inisiasi objek menggunakan konstruktornya secara langsung. Ini berguna jika Anda ingin pengguna memanggil metode lain (metode bawaan) untuk melakukan pembuatan objek secara tidak langsung.
2. Tipe Any dan Nothing
Di Kotlin, tipe tertinggi dalam hirarki tipe bernama Any. Sama dengan tipe Object di Java. Ini berarti bahwa semua kelas di Kotlin secara eksplisit mewarisi tipe Any termasuk String, Int, Double, dan lainnya. Tipe Any berisi tiga metode: equals, toString, dan hashcode.
Kita juga bisa memanfaatkan kelas Nothing di Kotlin dalam fungsi yang selalu mengembalikan pengecualian-dengan kata lain, untuk fungsi yang tidak berhenti secara normal. Saat sebuah fungsi mengembalikan nilai Nothing, maka kita tahu itu akan melakukan pengecualian. Tidak ada hal semacam ini di Java.
1 |
fun throwException(): Nothing { |
2 |
throw Exception("Exception message) |
3 |
}
|
Ini bisa berguna saat menguji penanganan kesalahan dalam unit test Anda.
3. Visibility Modifiers
Visibility modifiers membantu kami membatasi aksesibilitas API kami kepada publik. Kami dapat memberikan pengubah visibilitas yang berbeda untuk kelas, antarmuka, objek, metode, atau properti kami. Kotlin memberi kita empat pengubah visibilitas:
Public
Ini adalah default, dan class, function, property, interface, atau object yang memiliki modifier ini bisa diakses dari mana saja.
Private
Fungsi top-level, antarmuka atau kelas yang dideklarasikan sebagai private hanya bisa diakses dalam file yang sama.
Setiap fungsi atau properti yang dinyatakan private di dalam kelas, objek, atau antarmuka hanya dapat dilihat oleh anggota kelas, objek, atau antarmuka yang lain.
1 |
class Account { |
2 |
private val amount: Double = 0.0 |
3 |
}
|
Protected
Modifier protected hanya dapat diterapkan pada properti atau fungsi di dalam kelas, objek, atau antarmuka-tidak dapat diterapkan pada fungsi top-level, kelas, atau antarmuka. Properti atau fungsi dengan modifier ini hanya dapat diakses di dalam kelas yang mendefinisikannya dan subclass apapun.
Internal
Dalam sebuah proyek yang memiliki modul (modul Gradle atau Maven), kelas, objek, antarmuka atau fungsi yang ditentukan dengan modifier internal yang dideklarasikan di dalam modul itu hanya dapat diakses dari dalam modul itu.
1 |
internal class Account { |
2 |
val amount: Double = 0.0 |
3 |
}
|
4. Smart Casting
Casting berarti mengambil objek dari tipe lain dan mengubahnya menjadi tipe objek lain. Sebagai contoh, di Java, kita menggunakan operator instanceof untuk menentukan apakah tipe objek tertentu adalah tipe lain sebelum kita mentransmisikannya.
1 |
/* Java */
|
2 |
if (shape instanceof Circle) { |
3 |
Circle circle = (Circle) shape; |
4 |
circle.calCircumference(3.5); |
5 |
}
|
Seperti yang Anda lihat, kami memeriksa jika instance shape adalah Circle, dan kemudian kita secara eksplisit melemparkan shape ke tipe Circle sehingga kita bisa memanggil metode tipe circle.
Hal lain yang mengagumkan tentang Kotlin adalah kecerdasan kompilatornya saat berhubungan dengan casting. Sekarang mari kita lihat versi pada Kotlin.
1 |
/* Kotlin */
|
2 |
if (shape is Circle) { |
3 |
shape.calCircumference(3.5) |
4 |
}
|
Cukup rapi! Compiler cerdas mengetahui bahwa blok if akan dijalankan hanya jika objek shape adalah sebuah instance dari Circle - Jadi mekanisme casting dilakukan di balik layar untuk kita. Kita sekarang dapat dengan mudah memanggil properti atau fungsi dari tipe Circle di dalam blok if.
1 |
if (shape is Circle && shape.hasRadius()) { |
2 |
println("Circle radius is {shape.radius}") |
3 |
}
|
Sekarang, kondisi terakhir setelah && di dalam header if akan dipanggil hanya jikga saat kondisi pertama true. Jika shape bukan Circle, maka kondisi terakhir tidak akan dievaluasi.
5. Explicit Casting
Kita bisa menggunakan operator as (atau operator unsafe cast) untuk secara eksplisit melemparkan referensi tipe ke tipe lain di Kotlin.
1 |
val circle = shape as Circle |
2 |
circle.calCircumference(4) |
Jika operasi casting eksplisit itu error, perhatikan bahwa ClassCastException akan dijalankan. Untuk mencegah casting pengecualian dijalankan saat casting, kita bisa menggunakan operator safe cast (atau operator nullable cast) as?.
1 |
val circle: Circle? = shape as? Circle |
Operator as? akan mencoba untuk casting ke tipe yang dimaksud, dan mengembalikan nilai null jika nilainya tidak bisa dilemparkan alih-alih menjalankan pengecualian. Ingat bahwa mekanisme serupa telah dibahas di bagian Nullability di Nullability, Loops, and Conditions artikel dalam seri ini. Baca ke sana untuk penjelasan.
6. Objek
Objek di Kotlin lebih mirip dengan objek JavaScript daripada objek Java. Perhatikan bahwa sebuah objek di Kotlin bukanlah sebuah instance dari kelas tertentu!
Objek sangat mirip dengan kelas. Berikut adalah beberapa karakteristik objek di Kotlin:
- Bisa memiliki properti, metode, dan blok
init. - Properti atau metode ini dapat memiliki modifier visibilitas.
- Tidak dapat memiliki konstruktor (primer atau sekunder).
- Dapat di extend kelas lain atau menerapkan interface.
Mari sekarang gali cara membuat objek.
1 |
object Singleton { |
2 |
|
3 |
fun myFunc(): Unit { |
4 |
// do something
|
5 |
}
|
6 |
}
|
Kita menempatkan keyword object sebelum nama objek yang ingin kita buat. Sebenarnya, kita menciptakan satu saat kita membuat objek di Kotlin menggunakan construct object, karena hanya satu contoh dari sebuah objek yang ada. Anda akan belajar lebih banyak tentang hal ini saat kita membahas interoperabilitas objek dengan Java.
Singleton adalah pola perancangan perangkat lunak yang menjamin sebuah kelas memiliki satu contoh saja dan titik akses global untuk itu disediakan oleh kelas tersebut. Setiap kali beberapa kelas atau user meminta kelas, mereka mendapatkan instance kelas yang sama. Anda dapat melihat posting saya tentang pola tunggal di Java untuk mempelajari lebih lanjut tentang hal itu.
Anda dapat mengakses objek atau singleton di manapun dalam proyek Anda-asalkan Anda mengimpor paketnya.
1 |
Singleton.myFunc() |
Jika Anda seorang Java coder, ini adalah bagaimana kita biasanya membuat singletons:
1 |
public class Singleton { |
2 |
|
3 |
private static Singleton INSTANCE = null; |
4 |
|
5 |
// other instance variables can be here
|
6 |
|
7 |
private Singleton() {}; |
8 |
|
9 |
public static synchronized Singleton getInstance() { |
10 |
if (INSTANCE == null) { |
11 |
INSTANCE = new Singleton(); |
12 |
}
|
13 |
return(INSTANCE); |
14 |
}
|
15 |
|
16 |
// other instance methods can follow
|
17 |
}
|
Seperti yang bisa Anda lihat, menggunakan Kotlin membuat object membuatnya ringkas dan mudah untuk menciptakan singleton.
Objek di Kotlin bisa dimanfaatkan juga untuk menciptakan konstanta. Biasanya di Java, kita menciptakan konstanta di kelas dengan membuatnya menjadi public static final seperti ini:
1 |
public final class APIConstants { |
2 |
|
3 |
public static final String baseUrl = "https://www.myapi.com/"; |
4 |
|
5 |
private APIConstants() {} |
6 |
}
|
Kode di Java ini bisa dikonversikan ke Kotlin dengan lebih ringkas seperti ini:
1 |
package com.chike.kotlin.constants |
2 |
|
3 |
object APIConstants { |
4 |
val baseUrl: String = "http://www.myapi.com/" |
5 |
}
|
Disini kita mendeklarasikan konstanta APIConstants dengan properti baseUrl di dalam package com.chike.kotlin.constants. Di balik layar Java private static final baseUrl dibuat untuk kita dan diinisialisasi dengan URL string.
Untuk menggunakan konstanta ini dalam paket lain di Kotlin, cukup impor paketnya.
1 |
import com.chike.kotlin.constants.APIConstants |
2 |
|
3 |
APIConstants.baseUrl |
Interoperabilitas Java
Kotlin mengubah objek ke final class Java di balik layar. Kelas ini memiliki variabel statis dan privat INSTANCE yang memegang satu instance (singelton) kelas. Kode berikut menunjukkan bagaimana pengguna bisa memanggil objek Kotlin dari Java.
1 |
/* Java */
|
2 |
Singleton.INSTANCE.myFunc() |
Disinilah, kelas java dipanggil Singleton dihasilkan dengan public static final INSTANCE, termasuk fungsi public final myFunc().
Untuk membuat fungsi objek atau properti di Kotlin menjadi kelas statis Java yang dihasilkan, kita menggunakan anotasi @JvmStatic. Begini cara pengunaannya:
1 |
object Singleton { |
2 |
|
3 |
@JvmStatic fun myFunc(): Unit { |
4 |
// do something
|
5 |
}
|
6 |
}
|
Dengan menerapkan anotasi @JvmStaticke ke myFunc(), kompiler telah mengubahnya menjadi fungsi statis.
Sekarang pemanggil Java bisa memanggil seperti pemanggilan statis. Perhatikan bahwa menggunakan INSTANCE static untuk memanggil juga akan berhasil.
1 |
/* Java */
|
2 |
Singleton.myFunc() |
7. Companion Object
Sekarang kita sudah mengerti objek apa yang ada di Kotlin, mari dalami hal lainnya yang disebut Companion object.
Karena Kotlin tidak mendukung kelas statis, metode atau sifat seperti yang kita miliki di Java, tim Kotlin memberi kita alternatif yang lebih kuat yang disebut companion objects. Companion Object pada dasarnya adalah objek yang termasuk dalam kelas-kelas ini dikenal sebagai Companion class object. Ini juga berarti bahwa karakteristik yang saya sebutkan untuk objek juga berlaku untuk Companion object .
Membuat Companion object
Mirip dengan metode statis di Java, companion object tidak terkait dengan instance kelas tapi lebih dengan kelas itu sendiri-misalnya, metode statis bawaan, yang memiliki tugas untuk menciptakan instance kelas.
1 |
class Person private constructor(var firstName: String, var lastName: String) { |
2 |
|
3 |
companion object { |
4 |
fun create(firstName: String, lastName: String): Person = Person(firstName, lastName) |
5 |
}
|
6 |
}
|
Disini, kita membuat sebuah konstruktor private — Ini berarti bahwa pengguna di luar kelas tidak dapat membuat sebuah instance secara langsung. Di dalam blok Companion Object kita, kita memiliki sebuah fungsi create(), yang membuat objek Person dan mengembalikan nilainya.
Memanggil Companion Object Function
Inisiasi companion hanya akan diinisiasi bila diperlukan untuk pertama kalinya. Instansiasi companion object terjadi ketika sebuah instance dari kelas companion telah dibuat atau companion member objek telah diakses.
Mari kita lihat bagaimana cara memanggil companion object function di Kotlin.
1 |
val person = Person.create("Cersei", "Lannister") |
2 |
println(person.firstName) // prints "Cersei" |
Seperti yang bisa Anda lihat, ini seperti memanggil metode statis di Java seperti biasa. Dengan kata lain, kita hanya memanggil kelas dan kemudian memanggil member. Perhatikan bahwa selain fungsi, kita juga bisa memiliki properti di dalam companion object kita.
1 |
class Person private constructor(var firstName: String, var lastName: String) { |
2 |
init { |
3 |
count++ |
4 |
}
|
5 |
|
6 |
companion object { |
7 |
var count: Int = 0 |
8 |
fun create(firstName: String, lastName: String): Person = Person(firstName, lastName) |
9 |
|
10 |
init { |
11 |
println("Person companion object created") |
12 |
}
|
13 |
}
|
14 |
|
15 |
}
|
Catatlah bawa companion kelas memiliki akses tak terbatas ke semua properti dan fungsi yang dideklarasikan di companion object nya, sedangkan companion object tidak dapat mengakses anggota kelas. Kita bisa punya blok kode init di dalam companion object — Ini dipanggil segera saat companion object dibuat.
1 |
Person.create("Arya", "Stark") |
2 |
Person.create("Daenerys", "Targaryen") |
3 |
println(Person.count) |
Hasil eksekusi kode diatas adalah:
1 |
Person companion object created |
2 |
2 |
Ingat, hanya ada satu instance dari kelas companion object.
Kami juga bebas memberikan objek pendamping kami dengan sebuah nama.
1 |
// ...
|
2 |
companion object Factory { |
3 |
var count: Int = 0 |
4 |
fun create(firstName: String, lastName: String): Person = Person(firstName, lastName) |
5 |
}
|
6 |
// ...
|
Sekarang, kita akan menamainya Factory. Kita bisa memanggilnya seperti ini di Kotlin:
1 |
Person.Factory.create("Petyr", "Baelish") |
Gaya ini bertele-tele, jadi cara sebelumnya lebih disarankan. Tapi ini bisa berguna saat memanggil fungsi objek atau properti companion object dari Java.
Seperti yang saya katakan sebelumnya, seperti objek, companion object juga dapat mencakup properti atau fungsi, menerapkan antarmuka, dan bahkan melakukan extend kelas.
1 |
interface PersonFactory { |
2 |
fun create(firstName: String, lastName: String): Person |
3 |
}
|
4 |
|
5 |
class Person private constructor(var firstName: String, var lastName: String) { |
6 |
|
7 |
companion object : PersonFactory { |
8 |
override fun create(firstName: String, lastName: String): Person { |
9 |
return Person(firstName, lastName) |
10 |
}
|
11 |
}
|
12 |
}
|
Kita memiliki interface PersonFactory dengan fungsi create(). Lihat pada modifikasi companion object, sekarang terapkan antarmuka ini (Anda akan belajar tentang antarmuka dan pewarisan di Kotlin di artikel selanjutnya).
Interoperabilitas Java
Di balik layar, companion object dikompilasi sama seperti objek Kotlin yang dikompilasi. Dalam hal ini , dua kelas dihasilkan untuk kita: kelas final Person dan inner static final class Person$Companion.
Kelas Person berisi final static member yang disebut Companion - nilai static ini adalah objek dari inner class Person$Companion. Inner class Person$Companion juga memiliki anggotanya sendiri, dan salah satunya adalah public final function yang disebut create().
Perhatikan bahwa kami tidak memberi nama pada companion object kami, jadi kelas statis yang dihasilkan Companion. Jika kami telah memberinya nama, maka nama yang akan dihasilkan adalah nama yang kami berikan di Kotlin.
1 |
/* Java */
|
2 |
Person person = Person.Companion.create("Jon", "Snow"); |
Di sini, objek pendamping di Kotlin tidak memiliki nama, jadi kami menggunakan namanya Companion disediakan oleh compiler untuk pemanggil Java untuk memanggilnya.
Anotasi @JvmStatic yang diterapkan pada anggota companion object bekerja sama dengan cara kerjanya untuk objek biasa.
Companion Object Extensions
Demikian pula bagaimana fungsi ekstensi dapat melakukan extend fungsionalitas kelas, kita juga dapat extend fungsionalitas companion object. (Jika Anda ingin penjelasan fungsi ekstensi di Kotlin, kunjungi Advanced Functions tutorial di series).
1 |
class ClassA { |
2 |
|
3 |
companion object { |
4 |
|
5 |
}
|
6 |
}
|
7 |
|
8 |
fun ClassA.Companion.extFunc() { |
9 |
// ... do implementation
|
10 |
}
|
11 |
|
12 |
ClassA.extFunc() |
Di sini, kami mendefinisikan extension function extFunc() pada companion object ClassA.Companion. Dengan kata lain, extfunc() merupakan extend dari companion object. Kemudian kita bisa memanggil ekstensi seolah-olah itu adalah member function (bukan!) dari companion object.
Di balik layar, kompilator akan membuat fungsi utility function extFunc(). Objek penerima sebagai argumen untuk utility function ini adalah ClassA$Companion.
Kesimpulan
Dalam tutorial ini, Anda belajar tentang kelas dasar dan objek di Kotlin. Kami membahas hal berikut tentang kelas:
- Pembuatan Kelas
- Konstruktor
- Properti
- visibility modifiers
- smart casting
- explicit casting
Juga, Anda belajar tentang bagaimana objek dan companion object di Kotlin dapat dengan mudah mengganti metode statis, konstanta, dan kdoe singleton Anda di Java. Tapi bukan itu saja! Masih banyak yang harus dipelajari tentang kelas di Kotlin. Di posting berikutnya, saya akan menunjukkan fitur keren yang dimiliki Kotlin untuk pemrograman berorientasi objek. Sampai jumpa lagi!
Untuk mempelajari lebih lanjut tentang bahasa Kotlin, kunjungi Dokumentasi Kotlin. Atau lihat beberapa posting pengembangan aplikasi Android kami yang lain di Envato Tuts+!


Android SDKJava vs Kotlin: Haruskah Anda menggunakan Kotlin untuk Proses Pengembangan Android?Jessica Thornsby

Android SDKPengenalan Komponen Arsitektur Androidkomponen

Android SDKCara menggunakan Google Cloud Vision API dalam aplikasi AndroidAshraff Hathibelagal

Android SDKApakah itu Android Instant Apps?Android Instant Apps?













