Jumat, 23 September 2011

Javascript 2 (Konsep OOP di Javascript)

Pembahasan tentang konsep OOP di bagian kedua ini mungkin cenderung teoritis karena membahas fitur dari bahasa pemrograman dan biasanya dilakukan oleh orang sudah benar-benar paham. Tapi saya akan berusaha membahas sebatas kemampuan saya dan apabila ada kesalahan mohon diingatkan. Tulisan ini mencoba mengulas tentang tiga konsep dari OOP yaitu Encapsulation, Inheritance dan Polymorphism yang diterapkan di bahasa pemrograman Javascript serta isu lain yang berhubungan dengan object.

        a. PEMBUATAN OBJECT
       
Sebelum membuat sebuah object maka kita harus mendefinisikan class terlebih dahulu. Tidak seperti bahasa pemrograman lain yang menggunakan kata kunci "class", pembuatan class di Javascript sama seperti saat kita membuat fungsi biasa. Mungkin yang sedikit membedakan adalah adanya kesepakatan bahwa untuk pembuatan class maka nama fungsinya diawali dengan huruf kapital dan biasanya berupa kata benda sedangkan untuk pembuatan fungsi biasa diawali dengan huruf kecil (lowercase) dan berupa kata kerja. Berikut ini contoh definisi class di Javascript:

// ini class
function Kalkulator() {
    // ... disini method dan property
}
var kalk = new Kalkulator;

// ini fungsi biasa
function kalikan(a, b) {
    return a*b;
}

Pada dasarnya semua fungsi di Javascript bisa menjadi class :). Jika suatu fungsi diberi kata "new", maka dia akan menjadi fungsi constructor (fungsi yang otomatis dipanggil pertama kali saat object dibuat) seperti fungsi Kalkulator diatas.

        b. PROPERTY dan METHOD
       
Sebuah class pada umumnya memiliki setidaknya satu property ataupun method. Property adalah variabel yang didefinisikan dalam class tersebut sedangkan method adalah fungsi yang biasanya bekerja dengan property dari class. Untuk mengakses property atau method digunakan operator titik/dot "." setelah nama object/class yang ditentukan. Contohnya adalah "Math.PI" (mengakses property PI di class Math) dan "kalk.kalikan(2,3)" (mengakses method kalikan() di object kalk).

Class "Kalkulator" pada contoh sebelumnya masih belum memiliki property atau method yang didefinisikan. Di Javascript kamu bisa menambahkan property setiap saat secara dinamis pada object buatan class tersebut. Contohnya seperti ini:

function Kalkulator() { }
var kalk = new Kalkulator;
kalk.angka1 = 5;

alert(kalk.angka1); // 5

Masalahnya property "angka1" hanya dimiliki oleh objek "kalk" saja dan tidak dimiliki oleh objek lain seandainya kita membuat object lagi dari class Kalkulator. Kita bisa menggunakan kata kunci "this" di fungsi constructor untuk membuat property yang akan selalu ada pada semua object yang dibuat dari class Kalkulator dengan cara seperti berikut:

function Kalkulator() {
    this.angka1 = 5;
}
var kalk = new Kalkulator; // object baru
var kalk2 = new Kalkulator; // object lain

Kata kunci "this" untuk menggantikan nama object dirinya sendiri atau bisa dikatakan sebagai object saat ini. Sekarang semua object yang dibuat dari class Kalkulator pasti memiliki property "angka1". Tapi class Kalkulator masih kurang lengkap karena dia tidak memiliki method. Untuk menambahkan method sama seperti saat menambahkan property dan disini aku akan menggunakan fungsi anonim (baca bagian 1 - Javascript Pengetahuan Dasar).

function Kalkulator() {
    this.angka1 = 5;
    this.angka2 = 4;
    this.kalikan = function() {
        return this.angka1 * this.angka2;
    };
}
var kalk = new Kalkulator;
alert( kalk.angka1 ); // contoh akses dari luar object
alert( kalk.kalikan() ); // 20

        c. ENCAPSULATION
       
Pada class Kalkulator diatas kita dapat mengakses property angka1 dan angka2 dari luar object sehingga variabel ini terekspos secara umum (kita bisa mengubah nilai di angka1 dan angka2 dengan mudah dari luar object yang mungkin tidak kita inginkan). Salah satu konsep dari OOP adalah Encapsulation dimana kita bisa menyembunyikan property atau method dari akses yang berasal dari luar object sehingga anggota object lebih terlindungi dan objek dapat berjalan seperti yang diharapkan. Setiap property atau method bisa diberi hak akses apakah dia bisa diakses dari luar atau hanya bisa diakses dari dalam object saja. Encapsulation dianalogikan, adalah seperti tidak semua barang yang kita pakai bisa dan boleh dilihat orang kan?

Untuk membuat property atau method yang memiliki hak akses private (hanya bisa diakses dari dalam object saja) maka kita mengganti kata kunci "this" menjadi "var" di dalam fungsi constructornya. Sekarang kita ingin agar variabel "angka1" dan "angka2" memiliki akses private yaitu dengan cara:

function Kalkulator() {
    var angka1 = 5;
    var angka2 = 4;
    this.kalikan = function() {
        return angka1 * angka2;
    };
}
var kalk = new Kalkulator;
alert( kalk.angka1 ); // undefined karena sekarang private
alert( kalk.kalikan() ); // 20

Sekarang kita tidak bisa lagi mengakses property angka1 dan angka2 dari luar object seperti pada contoh diatas (baris kedua dari bawah) jika kita mencoba mengakses property angka1 yang muncul adalah tipe data "undefined" (tidak terdefinisikan). Dapat disimpulkan bahwa dengan menggunakan kata kunci "var" untuk property maka otomatis property tersebut akan memiliki hak akses private dan hanya dapat diakses dari dalam class saja. Sekarang muncul pertanyaan, bagaimana cara mengubah nilai property dengan akses private dari luar object?

        d. GETTER dan SETTER
       
Dalam OOP ada istilah getter dan setter yang berguna untuk mengubah data dari object yang memiliki akses private. Setter adalah method public yang berfungsi untuk mengeset nilai property yang private sedangkan getter berfungsi untuk mereturn nilai dari property yang memiliki akses private. Contohnya getter dan setter adalah seperti berikut:

function Kalkulator() {
    var angka1 = 0;
    var angka2 = 0;
    var hasil = 0;
   
    this.setAngka1 = function(a1) { // setter untuk angka1
        angka1 = a1;
    };
    this.setAngka2 = function(a2) { // setter untuk angka2
        angka2 = a2;
    };
    this.getHasil = function() { // getter untuk "hasil"
        return hasil;
    };
    this.kalikan = function() { // perkalian simpan ke "hasil"
        hasil = angka1 * angka2;
    }
}
var kalk = new Kalkulator;
kalk.kalikan();
alert( kalk.getHasil() ); // 0
kalk.setAngka1(3); // jadikan angka1 = 3
kalk.setAngka2(4); // jadikan angka2 = 4;
kalk.kalikan();
alert( kalk.getHasil() ); // 12;

Kita memiliki dua setter yaitu setAngka1 dan setAngka2 serta satu getter yaitu getHasil untuk mengubah atau mengakses nilai dari property dengan hak akses private. Selain tidak bisa diakses dari luar object, property dengan akses private juga tidak diwariskan pada object turunannya. Apa ini kok ada warisan segala?? Siapa yang meninggal?

        e. PEWARISAN/INHERITANCE
       
Salah satu konsep lain dari OOP adalah inheritance dimana property atau method suatu object bisa diwariskan pada object lain dengan tujuan untuk dikembangkan kemampuannya. Pada class Kalkulator diatas kita cuma mempunyai satu method "kalikan()" saja, nah daripada kita mengubah class tersebut lebih baik kalau property class tersebut kita turunkan pada class lain lalu kita kembangkan lagi class yang baru agar lebih baik. Mungkin kamu berpikir buat apa diturunkan ke class lain segala, diedit classnya aja kan sudah jadi dan lebih cepat? Ehm, iya kalau classnya seperti contoh diatas cuma memiliki beberapa property dan satu method, bagaimana kalau kamu diberi class yang memiliki ratusan property dan puluhan method yang kamu gak ngerti cara kerjanya?

Di Javascript, konsep inheritance diaplikasikan dengan menggunakan object prototype. Katanya prototype ini adalah template dari property yang dishare oleh semua instance dari object. Jadi semua object akan mewarisi nilai dari property dari prototype (semoga kata-kataku masuk akal :D). Kita langsung pada contoh saja:

// class induk/superclass
function Kalkulator() {
    var angka1 = 0; // private tidak diwariskan
    var    angka2 = 0; // ini juga private
    this.setAngka = function() {}; // ini public dan diwariskan
    this.getHasil = function() {}; // ini juga public
}
KalkulatorTambah.prototype = new Kalkulator; // turunkan class
KalkulatorTambah.prototype.constructor = KalkulatorTambah; // ubah constructor
// class anak/subclass
function KalkulatorTambah() {
    var angka1 = 1;
    var angka2 = 1;
    var hasil = 1;
    this.setAngka = function(a1, a2) { // override method induk
        angka1 = a1;
        angka2 = a2;
    };
    this.tambahkan = function() { // menambah method baru
        hasil = angka1 + angka2;
    };
    this.getHasil = function() { // override method induk
        return hasil;
    }
}
KalkulatorKali.prototype = new Kalkulator;
KalkulatorKali.prototype.constructor = KalkulatorKali;
// class anak lagi
function KalkulatorKali() {
    var angka1 = 2;
    var angka2 = 2;
    var hasil = 2;
    this.setAngka = function(a1, a2) {
        angka1 = a1;
        angka2 = a2;
    };
    this.kalikan = function() {
        hasil = angka1 * angka2;
    }
    this.getHasil = function() {
        return hasil;
    }
}

var kalk1 = new KalkulatorTambah;
var kalk2 = new KalkulatorKali;
kalk1.setAngka(2, 4);
kalk2.setAngka(2, 4);
kalk1.tambahkan();
kalk2.kalikan();
alert( kalk1.getHasil() ); // 6
alert( kalk2.getHasil() ); // 8

Yah, lumayan panjang juga untuk menunjukkan konsep inheritance ini :(. Pada contoh diatas kita buat dua anak turunan (subclass) dari class induk (superclass) Kalkulator yaitu KalkulatorTambah dan KalkulatorKali. Tiap turunan menambahkan method baru ataupun melakukan override (mengubah) method induknya. Semoga kamu bisa membayangkan apa yang terjadi pada class-class tersebut :). Dengan menuliskan "KalkulatorKali.prototype = new Kalkulator" itu berarti kita mewariskan semua property dengan akses public dari object "Kalkulator" ke object "KalkulatorKali". Agar constructor "KalkulatorKali" adalah dirinya sendiri (dan bukan induk) maka kita harus menuliskan "KalkulatorKali.prototype.constructor = KalkulatorKali" karena jika tidak maka object turunan akan tetap memanggil constructor induknya.
Jika kita memanggil sebuah property atau method maka Javascript pertamakali kali mencarinya di definisi classnya apakah didefinisikan secara eksplisit. Jika tidak ditemukan Javascript akan mencari ke prototype class tersebut dan jika tetap tidak ketemu akan dicari di class induknya. Begitu seterusnya hingga Javascript menemukan property yang kita panggil tersebut.

        f. POLYMORPHISM
       
Konsep terakhir dari OOP adalah polymorphism. Kamu lihat lagi contoh diatas dimana ada dua object yang memiliki method yang sama (setAngka dan getHasil). Nah, itu yang disebut polymorphism!. Sesederhana itukah? Jawabannya adalah iya.

Sekali lagi saya ingin mengatakan bahwa pembahasan ini cenderung teoritis artinya kamu gak perlu risau jika kodemu tidak seperti ini (punya inheritance, encapsulation, dsb). Tapi alangkah baiknya, karena tujuan OOP itu untuk mempermudah kerja programmer maka seharusnyalah kamu belajar untuk mengaplikasikan semua konsep diatas pada kode yang kamu buat. Jika kamu bekerja sendiri tanpa tim mungkin tidak masalah tapi jika bekerja dengan tim maka penggunaan OOP akan mempercepat kerjamu dan orang lain dalam timmu. Misalkan, kamu langsung saja memberi tahu kalau method yang public ini, ini dan ini, nah orang lain gak perlu baca keseluruhan kodemu atau edit sana edit sini, mereka cukup menggunakan class buatanmu yang sudah ada, atau jika perlu mereka bisa membuat turunan dari class yang kamu buat, selesai.


        g. CARA LAIN PEMBUATAN OBJECT
       
Pada contoh sebelumnya kita harus mendefinisikan dulu class untuk object yang akan kita buat, nah ada cara baru yang akan aku perkenalkan yaitu pembuatan object secara langsung seperti berikut:

var kalk = {
    "hasil" : 0,
    "kalikan" : function(a1, a2) {
        this.hasil = a1 * a2;
    },
    "getHasil": function() {
        return this.hasil;
    }
}
kalk.kalikan(2,3);
alert( kalk.getHasil() );

Tidak seperti contoh sebelumnya dimana kita harus membuat fungsi constructor lebih dahulu, sekarang kita bisa langsung membuat object secara instan. Objek yang kita inginkan sudah jadi, dan siap digunakan tanpa harus menulis fungsi constructor atau kata kunci "new" lagi. Seperti contoh diatas, untuk membuat object digunakan tanda kurung kurawal {} dan semua method atau properti ditulis dengan bentuk: { "namanya": "nilainya" } dan tiap properti dipisahkan dengan tanda koma (*perhatikan bahwa tanda koma tidak boleh ada setelah elemen terakhir). Object bentukan ini bisa langsung di assign ke variabel seperti contoh diatas langsung di assign ke variabel "kalk" ataupun di pass ke suatu fungsi sebagai parameter seperti berikut:

showResult({ "hasil": 0, "angka1": 2, "angka2": 4 });

Contoh diatas adalah contoh melakukan pass sebuah object kedalam fungsi. Yang perlu kamu catat adalah dengan membuat object seperti ini maka semua property atau method yang kamu deklarasikan akan memiliki hak akses public. Sebagian programmer mengawali nama property atau method dengan underscore (_) untuk menandakan bahwa dia tidak seharusnya diakses langsung dan memiliki hak akses private (contohnya: "_init()", "_width", dsb.)

        h. JSON (JavaScript Object Notation)
       
JSON mirip dengan penulisan object menggunakan kurang kurawal {} yang biasanya digunakan untuk pertukaran data (selain menggunakan XML). Karena JSON berupa string maka JSON dapat dipass ke URL atau metode request lain sehingga object yang sudah jadi tersebut siap digunakan tanpa harus diproses lagi oleh client ataupun oleh server. PHP memiliki dua fungsi yang berhubungan dengan JSON yaitu "json_encode" (melakukan encode object/array PHP ke JSON) dan "json_decode" (melakukan decode JSON ke dalam object/array PHP). Contoh penggunaan fungsi json_decode adalah seperti berikut:

<?php
$json = '{"nama": "amir"}';
$obj = json_decode($json);
print $obj->{'nama'}; // amir
?>

JSON bukanlah Javascript tapi subset dari Javascript sehingga spesifikasi JSON sedikit berbeda. Kode dibawah ini valid Javascript tapi tidak untuk JSON:

var data = { 'nama': "amir", umur: 27, "alamat": "indonesia" }

Alasan tidak valid JSON karena pada JSON nama properti dan nilainya harus diapit tanda double quoute (") dan tidak seperti kode diatas properti nama menggunakan single quote dan umur bahkan tidak menggunakan tanda quote sama sekali.

Karena JSON digunakan untuk pertukaran data maka kita tidak bisa mempass method melalui JSON. Nah bagaimana Javascript menghandle JSON? Jika Javascript menerima data dalam bentuk JSON maka sangat mudah mengubahnya menjadi object yaitu dengan menggunakan fungsi "eval()" atau bila tersedia bisa menggunakan method "window.JSON.parse()" untuk mengubah string JSON ke object yang sebenarnya.
       
        i. STATIC METHOD / PROPERTY
       
Secara singkat, static method atau property adalah method/property yang dimiliki oleh class dan bukan object sehingga untuk mengakses static method/property kita tidak perlu menggunakan kata kunci "new". Secara singkat cara pembuatan static method/property pada Javascript sama seperti menggunakan Prototype tapi sekarang kita hilangkan kata prototype seperti berikut:

function Kalkulator() {
    // definisi class
}
Kalkulator.kalikan = function(a1, a2) { // static method
    return a1 * a2;
}
// Tanpa new dan langsung nama class diikuti nama method kalikan
alert( Kalkulator.kalikan(2, 3) );

Static properti atau method biasanya digunakan jika kamu merasa bahwa ada method/property yang tidak tergantung pada property/method lain dari class tersebut sehingga akan lebih efektif bila kamu membuatnya menjadi static.
       
        -----------------
Saya rasa pembahasan tentang konsep OOP di Javascript sudah dicukupkan sampai sini saja dan semoga yang sedikit ini bisa bermanfaat. Terima kasih atas waktu dan perhatiannya dan sampai jumpa. Oh iya, pada bagian ketiga nanti saya akan membahas tentang DOM dan AJAX. See you!

Tidak ada komentar:

Posting Komentar