Class pada Kotlin - Lanjutan

Muhammad Fajri
Thursday, 15 April 2021

Bismillahirrahmanirrahim.

Kembali lagi kita lanjutkan pembahasan mengenai OOP (Object Oriented Programming) dan melanjutkan pembahasan mengenai class.

Properties

Property pada class atau object dibuat dengan mendefinisikan member variable dan menyediakannya accessor method. Function ini mengikuti penamaan yang biasa di mana nama dari member variable akan diawali dengan get dan set.

Berikut contoh program dalam Java:

class Person {
    private String name;

    public String getName() {
        return this.name
    }
    public void setName(String arg) {
        this.name = arg;
    }

    public static void main(String []args) {
        Person person = new Person();
        person.setName("John Doe");
        System.out.println(person.getName());
    }
}

Ini contoh pembuatan class Java yang mendefinsikan sebuah property yaitu name. name ini ditetapkan sebagai private sehingga akses pada state ini hanya dapat dikontrol melalui accessor (getName() dan setName()). Ini merupakan pengungkapan kodenya dalam bahasa Java karena bahasa ini tidak memiliki cara tersendiri yang mendukung properties. Kita pun dapat mengikuti cara ini di Kotlin, tapi kita tidak harus karena Kotlin memiliki dukungan untuk properties.

Contoh programnya:

class Person(_name: String) {
    val name: String = _name
}

fun main() {
    var person = Person("John Smith")
    println(person.name)
}

Constructor diambil di dalam parameter (_name: String). val name: String = _name kita mmiliki akses pada parameter melalui constructor dari sini. println(person.name) ini terlihat seperti kita melakukan akses secara langsung pada nama member variable, tetapi tidak. Ini sebenarnya memanggil accessor method get.

Definisi class tadi dapat disederhanakan menjadi:

class Person(val name: String)

Kode di sini merupakan cara paling ringkas untuk mendefinisikan property di Kotlin. Catatan perubahan yang kita buat yaitu:

  • Parameter yang ada pada primary constructor dideklarasikan dengan val. Ini cara yang efektif untuk membuat property pada parameter constructor. Kita dapat menggunakan var dan akan berfungsi dengan baik.
  • Kita tidak lagi harus membedakan nama identifier pada parameter constructor dengan member variable, karena itu kita menghilangkan garis bawah (_) pada variabel.
  • Kita dapat menghilangkan seluruh body dari class karena kita tidak membutuhkannya lagi. Body hanya memuat kode untuk mengirim nilai dari parameter constructor menuju member variable. Karena Kotlin akan secara otomatis mendefinisikan backing field untuk parameter constructor, kita tidak harus melakukan apa-apa lagi di dalam body dari class.

Definisi class tadi merupakan cara paling dasar untuk mendefinisikan object data di Kotlin (programmer Java mengenalnya sebagai POJO atau plain old java object). Hanya dengan menggunakan val atau var pada parameter constructor, secara otomatis kita dapat mendefinisikan property dengan method yang sesuai. Akan tetapi, akan ada keadaan di saat kita akan butuh kontrol yang lebih pada proses “getting” dan “setting” dari property ini, Kotlin memungkinkan kita untuk melakukannya.

Berikut cara membuatnya:

  • Deklarasikan property di dalam body class, bukan di primary constructor.
  • Sediakan method getter dan setter di body class.

Sintaksnya yaitu:

var <property name>: <property type> = <initializer>
<getter>
<setter>

Berikut contoh dasar penggunaan custom accessor method.

class Employee {
    var name: String = ""
    get() {
        Log("Getting lastname")
        return field
    }
    set(value) {
        Log("Setting value of lastname")
        field = value
    }
}
fun Log(msg: String) {
    println(msg)
}
fun main() {
    var emp = Employee()
    emp.name = "John Doe"
    println(emp.name)
}

var name: String = "" kita mendefinisikan property di dalam body class, daripada kita membuatnya menjadi parameter di dalam primary constructor dan kita inisialisasi sebagai String kosong terlebih dahulu. Sintaks get() terlihat seperti sintaks untuk mendefinisikan sebuah function, namun tidak menuliskan kata kunci fun sebelumnya. Log("Getting lastname"), ini dimana kita menuliskan kode custom. Statement ini akan dieksekusi setiap kali seseorang mencoba untuk mengakses nama property-nya. Kata kunci field mengacu pada backing field yang secara otomatis disediakan oleh Kotlin ketika kita mendefinisikan sebuah property bernama name. Member variable name bukan variabel yang sederhana, Kotlin membuatkan backing field otomatis untuknya, tetapi kita tidak memiliki akses langsung terhadap variabel tersebut. Kita dapat mengaksesnya melalui kata kunci field. Parameter value ini sama dengan nilai yang akan di-assign pada property setelah object Employee dibuat (emp.name = "John Doe"). field = value, setelah membuat custom logic, sekarang kita dapat mengeset nilai dari field. emp.name = "John Doe" ini akan memicu accessor method set(). println(emp.name) akan memicu accessor method get().

Data Classes

Sebelumnya, kita telah melihat bagaimana dengan mudahnya kita dapat membuat POJO analog di Kotlin. Kita hanya mendefinisikan property di dalam class dan program pun akan jalan. Data object yang dibuat seperti itu akan cukup bagus untuk use-case sederhana. Tetapi di sataa kita memerlukan sesuatu seperti menyimpan nilai object di collection atau membandingkan object dengan yang lainnya untuk melihat kesamaan konten, maka class dengan property yang tadi tidaklah cukup. Hanya satu hal yang kita butuhkan di Kotlin yaitu membuatkan class sebuah data class. Contoh program:

data class Employee(val name: String)

fun main() {
    val e1 = Employee("John Doe")
    val e2 = Employee("John Doe")

    println(e1)
    println(e1 == e2)
}

Untuk membuatkan data class dari class apapun di Kotlin, kita hanya menggunakan kata kunci data pada deklarasi class. println(e1) akan mencetak output Employee(name=John Doe). Permbandingan ini mengembalikan nilai true.

Visibility Modifiers

Kotlin hampir semuanya menggunakan kata kunci yang sama dengan Java untuk mengontrol visibility. Kata kunci public, private, dan protected sama maksudnya di Kotlin seperti yang dilakukan di Java. Tetapi, default visibility yang dimiliki itulah yang membuat perbedaan. Di Kotlin, jika modifier visibility dihilangkan (tidak dituliskan), maka default visibility-nya adalah public. Selain class tersebut, membernya pun akan bersifat public.

Berbeda dengan Java yang mana default visibility sebuah class merupakan package-private, artinya apa yang tersedia untuk class tersebut hanya yang berada dalam package yang sama. Di Kotlin, tidak memiliki package-private sebagai persamaan karena Kotlin tidak menggunakan package sebagai cara untuk mengelola visibility. Package di Kotlin hanya sebagai cara untuk mengorganisasi file.

Sebagai ganti package-private di Java, Kotlin memperkenalkan kata kunci internal yang artinya visible dalam sebuah module. Module ini hanya collection file dapat berupa module atau project Intellij, project Eclipse, project Maven, atau project Gradle.

Untuk menunjukkan visibility sebuah modifier, perhatikan contoh berikut.

internal open class Foo {
    private fun boo() = println("boo")
    protected fun doo() = println("doo")
}

fun Foo.bar() {
    boo()
    doo()
}

fun main() {
    var fu = Foo()
    fu.bar()
}

Class Foo ditandai sebagai internal yang membuat visibility-nya hanya di dalam class dan top-level function yang berada dalam module yang sama dan visibility-nya juga ditandai sebagai internal. fun Foo.bar() merupakan kesalahan. Extension function ditandai sebagai public tetapi receiver dari function tersebut (Foo) ditandai sebagai internal. Class Foo sedikit tersembunyi daripada extension function, karenanya, Kotlin tidak mengijinkan. boo() dan doo() yang masing-masing private dan protected tidak dapat diakses dari sini (function Foo.bar()).

Agar bisa diakses, class dan member-nya harus dibuat internal. Begitu pun function yang ingin mengakses member dari class, harus dibuat internal.

internal open class Foo {
    internal fun boo() = println("boo")
    internal fun doo() = println("doo")
}

internal fun Foo.bar() {
    boo()
    doo()
}

fun main() {
    var fu = Foo()
    fu.bar()
}

Output:

boo
doo

Access Modifier

Access modifier di Kotlin yaitu final, open, abstract, dan override. Ini mempengaruhi inheritance. Sejauh ini, hanya kata kunci abstract yang belum digunakan. Kata kunci abstract memiliki arti yang sama di Kotlin dan di Java, diaplikasikan pada class dan function.

Jika class ditandai sebagai abstract maka secara mutlak ia bersifat open, sehingga kita tidak memerlukan modifier open. Interface tidak perlu dideklarasikan sebagai abstract dan open, karena secara mutlak ia telah bersifat abstract dan open.

Object Declaration

Kata kunci static Java tidak terdaftar sebagai kata kunci di Kotlin. Tidak ada persamaan static ini, sebagai gantinya, Kotlin memperkenalkan kata kunci object dan companion. Kata kunci object memungkinkan kita untuk mendefinisikan class dan instance-nya pada waktu yang sama. Secara lebih spesifik, ia hanya mendefinisikan satu instance dari class itu. Contoh programnya dapat dilihat berikut ini.

object Util {
    fun foo() = println("foo")
}
fun main() {
    Util.foo()
}

Output:

foo

Kita mengganti posisi class dengan kata kunci object. Efektifnya, ini mendefinisikan class dengan instance yang dapat dibuat hanya satu. Untuk memanggil function yang didefinisikan di dalam object ini, kita gunakan gunakan dot (.) dengan nama object-nya –seperti memanggil static method di Java.

Deklarasi object dapat memuat hampir semua hal yang bisa ditulis di class, seperti initializer, property, function, dan member variable. Hanya satu hal yang tidak bisa ditulis yaitu constructor. Alasannya, karena kita tidak membutuhkan constructor. Deklarasi object membuat sebuah instance pada saat definisi, jadi constructor tidak diperlukan.

Contoh programnya:

object Util {
    var name = ""
    set(value) {
        field = value
    }
    init {
        println("Initializing Util")
    }
    fun foo() = println(name)
}
fun main() {
    Util.name = "Bar"
    Util.foo()
}

Output:

Bar

Referensi

  1. Hagos, Ted. 2018. Learn Android Studio 3 with Kotlin: Efficient Android App Development. Apress: Manila.