MINGGU V : PBO (PEWARISAN) Pertemuan minggu ini akan membahas konsep lanjutan dari Pemrograman Berorientasi Objek yaitu Generalisasi/Spesialisasi. Pembahasan topik pada pertemuan ini meliputi pewarisan, overriding, interface dan kelas abstract. Kompetensi Khusus Setelah mengikuti perkuliahan ini diharapkan mahasiswa memiliki pemahaman tentang konsep generalisasi/spesialisasi dalam PBO. Materi Salah satu konsep dasar dalam Pemrograman Berorientasi Objek adalah generalisasi/spesialisasi. Dalam konsep ini dinyatakan bahwa kelas dapat dikelompokkan (diklasifikasikan) dalam sebuah kelompok dikarenakan kesamaan properti atau perilaku kelas-kelas yang ada dalam kelompok tersebut. Namun setiap kelas yang ada dalam kelompok tersebut memiliki sesuatu yang spesifik yang membedakannya dengan kelas lain dalam kelompok tersebut. Misalkan terdapat 3 kelas yaitu Anjing, Paus dan Kuda. Ketiga kelas tersebut dapat diklasifikasikan dalam sebuah kelas yang bernama Mamalia karena ketiga jenis kelas tersebut merupakan kelas dari binatang mamalia. Semua kelas yang berada dalam kelas Mamalia memiliki kesamaan yaitu memiliki perilaku menyusui dan melahirkan anaknya. Namun walaupun ketiga kelas tersebut memiliki kesamaan perilaku dan properti, ketiga kelas tersebut memiliki sesuatu yang spesifik yang membedakan masing-masing kelas. Kelas Anjing memiliki perilaku menggonggong, kelas paus memiliki perilaku berenang dan kelas Kuda memiliki perilaku meringkik. Bisa juga ketiga kelas tersebut memiliki perilaku yang sama tapi berbeda dalam implementasinya seperti cara bergerak. Inilah konsep generalisasi/spesialisasi. Kelas Mamalia merupakan generalisasi dari kelas Anjing, Paus dan Kuda dan kelas Anjing, Paus, Kuda merupakan spesialisasi dari kelas Mamalia. Dalam C# konsep generalisasi/spesialisasi ini diimplementasikan melalui turunan (inheritance), interface dan kelas abstrak yang akan kita bahas satu persatu. Inheritance Inheritance merupakan proses untuk mendefinisikan sebuah kelas baru (kelas anak) yang berasal dari kelas yang sudah ada (kelas baru). Dalam inheritance ini terjadi pewarisan properti dan perilaku dari kelas induk ke kelas anak. Semua properti yang dimiliki oleh kelas induk akan dimiliki oleh kelas anak dengan sendirinya. Dalam hal ini terjadi code sharing antara kelas induk dengan kelas anak. Kelas yang dijadikan kelas induk merupakan kelas 32
yang general sedangkan kelas anak merupakan kelas induk yang memiliki sesuatu yang spesifik. Untuk membuat kelas melalui inheritance dengan C# dilakukan dengan menggunakan operator :. Misalkan Kita akan membuat sebuah kelas Kucing dari kelas Mamalia. classmamalia{ publicintumur; publicstringjenismakanan; publicvoidmenyusui(){ Console.WriteLine("Menyusuianaknya"); } publicvoidmelahirkan(){ Console.WriteLine("Melahirkananak"); } } classpaus:mamalia{ publicvoidberenang(){ Console.WriteLine("Berenang..."); } } Contoh diatas memperlihatkan bahwa kelas Paus dibuat melalui proses inheritance kelas Mamalia. Seluruh properti dan method yang dimiliki oleh kelas Mamalia dimiliki oleh kelas Paus. Bahkan paus memiliki satu method tambahan yang tidak dimiliki oleh kelas Mamalias yaitu method berenang. Inisialisasi objek dari kedua kelas sama seperti menciptakan objek dari kelas umumnya. Mamaliamamalia=newMamalia(); Pausikanpaus=newPaus(); Kelas induk disebut juga dengan nama superclass atau parent class dan kelas anak disebut juga dengan nama subclass atau child class. Kelas anak didapatkan melalui proses spesialisasi kelas induk. Oleh karena kelas anak berasal dari kelas induknya dan mewarisi semua properti dan perilaku induknya maka kelas anak dapat diperlakukan layaknya kelas induknya. Bahkan kelas anak dapat menempati posisi yang seharusnya ditempati oleh kelas induknya. Contohnya adalah sebagai berikut Mamaliamamalia=newPaus(); 33
Pada contoh diatas, variabel mamalia merupakan variabel bertipe Mamalia, sehingga hanya bisa menyimpan objek dari kelas Mamalia. Oleh karena dikarenakan kelas Paus merupakan kelas anak dari kelas Mamalia, maka objek dari kelas Paus (kelas anak) dapat disimpan pada variabel bertipe Mamalia (kelas induk). Namun walaupun objek dari kelas Paus memiliki method berenang, method tersebut tidak bisa dipanggil melalui variabel mamalia dikarenakan tipe data variabel mamalias adalah Mamalia dimana kelas Mamalia tersebut tidak memiliki method berenang. Inheritance akan menciptakan hirarki kelas sehingga tercipta relasi antar kelas. Kelas yang menjadi kelas induk pertama sekali disebut dengan kelas root. Kelas ini berdiri dengan sendirinya (tidak diturunkan dari kelas lainnya). Dari kelas root ini bisa diturunkan lagi menjadi kelas-kelas lainnya. Kelas baru bisa diciptakan dengan menurunkan kelas yang diturunkan dari kelas root dan begitu seterusnya. Hal ini akan membentuk inheritance chain yang menunjukkan urutan kelas-kelas tersebut seperti pada gambar dibawah ini. Kelas C diturunkan menjadi kelas C11 dan C12. Kelas C11 diturunkan menjadi kelas C21, C22, C23. Kelas C31diturunkan dari kelas C22. Hubungan turunan dalam dalam inheritance chain ini bersifat transitive. Hubungan transitive Jika C1 adalah subclass dari C2 dan C2 juga subclass dari C3 maka C1 juga merupakan subclass dari C3. C11 dan C12 merupakan direct subclass dari kelas C. Kelas C21, C22, dan C23 merupakan indirect subclass dari kelas C. Inheritance chain ini hanya bisa dilihat secara linear ke atas. Artinya kelas C21 bisa mengetahui kelas-kelas yang menjadi nenek moyangnya. Artinya kelas C21 akan mewarisi 34
seluruh properti yang method yang dimiliki oleh kelas-kelas nenek moyangnya. Namun kelas C21 tidak mengetahui tentang keberadaan saudara-saudaranya yaitu kelas C22 dan C23. Jangan analogikan inheritance chain ini dengan silsilah keluarga, karena terlalu menyedikan untuk diceritakan. Sealed Class & Sealed Method Jika sebuah kelas tidak diinginkan memiliki kelas anak, maka kelas tersebut dapat dikunci. Penguncian kelas ini membuat kelas tersebut tidak memungkinkan untuk memiliki kelas anak. Penguncian kelas dilakukan dengan menggunakan keyword sealed seperti contoh dibawah ini. sealedclassmandulparent { } Penggunaan keyword sealed tersebut mengunci kelas yang bersangkutan untuk tidak bisa mewariskan properti dan method-nya ke kelas lain. Selain berlaku terhadap kelas, keyword sealed juga berlaku untuk method. Method yang menggunakan kata kunci sealed tidak akan diwariskan ke kelas turunannya. Overriding Pada pertemuan sebelumnya telah dibahas tentang polymorphisme. Salah satu bentuk polymorphisme adalah overriding. Overriding berarti mendefinisikan ulang method yang terdapat dalam kelas induk. Method yang bisa dioverriding hanyalah method yang memiliki keyword virtual di kelas induknya dan method yang meng-overriding harus menggunakan keyword override Overriding ini sering terjadi saat implementasi method pada kelas induk tidak sesuai dengan perilaku kelas anaknya. Misalnya saja kelas Mamalia. Asumsikan saja kelas Mamalia memiliki method pindah. Pada umumnya setiap Mamalia pindah tempat dengan cara berjalan atau berlari. Namun Paus memiliki cara yang berbeda dan tidak memungkinkan untuk berjalan atau berlari. Kelas Paus tidak mungkin menggunakan method pindah yang diwariskan kelas induknya kepadanya karena cara berpindah kelas Paus berbeda dengan kelas Mamalia pada umumnya. Oleh karena itu method pindah yang diwariskan dari induknya perlu didefinisikan ulang agar sesuai dengan kondisi kelas Paus. Contoh implementasi dari kasus diatas adalah sebagai berikut 35
classmamalia{ publicvirtualvoidpindah() { Console.WriteLine("Lari..."); } } classkucing:mamalia { } classpaus:mamalia{ publicoverridevoidpindah(){ Console.WriteLine("Berenang..."); } } Pada contoh diatas dapat dilihat ada 3 kelas yaitu Mamalia, Kucing dan Paus. Kelas Kucing dan Paus merupakan turunan dari kelas Mamalia. Oleh karena method pindahnya kelas Paus memiliki metode yang berbeda dengan dengan metode pindah pada kelas induknya, maka pada kelas Paus perlu didefinisikan kembali metode pindah yang dimilikinya. Dalam beberapa kasus overriding, method yang dioverride pada kelas induk perlu untuk dipanggil kembali pada method yang sama di kelas anaknya. Pemanggilan method induk oleh kelas anak dapat dilakukan dengan menggunakan keyword base. Keyword base digunakan untuk mereferensikan kelas induknya. Misalnya kelas Anjing yang juga termasuk dalam kelas Mamalia. Anjing merupakan Mamalia yang pindah dengan cara berlari dan juga bisa berenang. Maka implementasi method pindah pada kelas Anjing dapat dibuat menjadi seperti berikut ini. classanjing:mamalia { publicoverridevoidpindah() { base.pindah(); Console.WriteLine("Berenang..."); } } Pada contoh diatas, method pindah yang dimiliki kelas Anjing akan menjalankan method pindah yang dimiliki oleh kelas induknya melalui statement base.pindah() dan kemudian baru menjalankan implementasi method pindah yang dimiliki oleh kelas Anjing itu sendiri. 36
Interface Interface merupakan betnuk kelas khusus dimana kelas tersebut tidak memiliki kode program maupun data. Dalam interface hanya terdapat deklarasi method tapi tidak ada implementasi kodenya. Oleh karena tidak memiliki data dan implementasi kode, objek tidak bisa diciptakan dari interface. Sebuah interface dibuat dengan menggunakan keyword interface. Beberapa hal yang perlu diperhatikan dalam menulis interface adalah sebagai berikut: 1. Interface tidak boleh diturunkan dari kelas atau struct lain. 2. Interface hanya mendeklarasikan method. Properti tidak boleh didelarasikan dalam interface. Begitu juga dengan tipe data seperti enumerations, kelas lain, atau struct. 3. Method yang dideklarasikan dalam interface tidak boleh memiliki akses level. Hal ini dikarenakan semua method yang dideklarasikan dalam interface memiliki akses level public. 4. Interface tidak boleh mendeklarasikan constructor dan destructor. Contoh deklarasi interface dapat dilihat pada kode sumber dibawah ini. interfaceibidangdatar { StringGetID(); doublehitungluas(); } Pada contoh diatas dideklarasikan sebuah interface bernama IbidangDatar. Dalam interface tersebut memiliki 2 buah method yaitu GetID dan HitungLuas. Perhatikan deklarasi method tersebut, dalam deklarasi method tersebut tidak dideklarasikan akses level method. Hal ini bukan berarti hak akses method tersebut mengikuti akses level default yaitu private akan tetap akses level kedua method tersebut sudah ditetapkan public. Dalam interface diatas, method yang dideklarasikan tidak memiliki implementasi. Hanya deklarasi tipe data, nama method dan daftar argumen jika ada. Saran penamaan interface Gunakan I pada awal nama interface. Seperti yang telah dinyatakan sebelumnya, objek tidak bisa diciptakan dari sebuah interface. Untuk apa gunanya interface kalau tidak bisa digunakan untuk membuat objek? Kegunaan interface memang bukan sebagai cetakan untuk membuat objek akan tetapi lebih berfungsi sebagai kontrak. Interface harus diimplementasikan oleh kelas lain agar dapat berguna. 37
Kelas lain yang mengimplementasikan sebuah interface harus mengimplementasikan seluruh method yang dideklarasikan dalam interface tersebut. Error akan muncul jika ada sebuah method yang dideklarasikan dalam interface tidak didefinisikan pada kelas yang mengimplementasikan interface tersebut. Contoh penggunaan interface dapat dilihat pada contoh berikut ini. classpersegipanjang:ibidangdatar { publicstringid; publicdoublepanjang; publicdoublelebar; publicstringgetid() { returnid; } publicdoublehitungluas(){ doubleluas=panjang*lebar; returnluas; } } Penggunaan interface harus melalui proses implementasi interface pada suatu kelas. Operator yang digunakan untuk mengimplementasikan interface sama dengan operator yang digunakan untuk inheritance. Namun untuk interface disebut mengimplementasikan sedangkan pada inheritance disebut mewarisi. Kelas yang mengimplementasikan interface IBidangDatar harus mendefinisikan method GetID() dan HitungLuas() dalam kelas PersegiPanjang. Selanjutnya barulah kelas PersegiPanjang yang telah mengimplementasikan interface IBidangDatar dapat digunakan untuk menciptakan objek. Penggunaan kelas PersegiPanjang sama seperti penggunaan kelas seperti biasa. Contoh penggunaannya dapat dilihat pada kode dibawah ini. PersegiPanjangpp=newPersegiPanjang(); pp.id="persegippanjangp01"; pp.lebar=23; pp.panjang=20; Console.WriteLine(">LuasBidangDatar{0}={1}", pp.getid(), 38
pp.hitungluas()); Sebuah kelas bisa mengimplementasikan lebih dari satu interface. Jika sebuah kelas mengimplementasikan lebih dari satu interface, maka setiap method yang ada dalam interface yang diimplementasikan harus didefinisikan dalam kelas yang mengimplementasikan interface tersebut. Hal ini berbeda dengan inheritance dimana pada inheritance sebuah kelas hanya boleh diturunkan dari 1 kelas lain, tidak boleh lebih. Kelas Abstrak Kelas abstrak merupakan kelas yang didefinisikan tidak lengkap. Sama halnya dengan interface, kelas abstrak tidak bisa digunakan untuk membuat objek. Untuk membuat objek, kelas abstrak harus diturunkan terlebih dahulu. Namun berbeda dengan interface, pada kelas abstrak bisa terdapat deklarasi properti dan method. Secara umum, kelas abstrak sama seperti kelas biasa, namun ada bagian-bagian tertentu yang dibiarkan kosong untuk dikustomisasi oleh kelas turunannya. Kelas abstrak dibuat dengan menggunakan kata kunci abstract. Sebuah kelas abstrak bisa dibuat dari sebuah kelas yang diturunkan dari kelas lainnya. Berikut ini adalah contoh kelas abstrak. abstractclassbidangdatar { publicstringid; publicdoublepanjang; publicdoublelebar; publicstringgetid() { returnid; } abstractpublicdoublehitungluas(); } Pada contoh diatas terdapat kelas abstrak BidangDatar. Dalam kelas abstrak tersebut terdapat sebuah method abstrak bernama HitungLuas(). Method abstrak ini merupakan method yang harus didefinisikan dalam kelas turunan BidangDatar tersebut. Method abstrak hanya boleh ada dalam kelas abstrak 39
Contoh implementasi kelas abstrak dapat dilihat pada kode dibawah ini. classpersegi:bidangdatar { publicoverridedoublehitungluas() { returnpanjang*lebar; } } Method HitungLuas() yang mendefinisikan abstract method HitungLuas() pada kelas abstrak BidangDatar harus menggunakan keyword override. 40