BAB 12 PEWARISAN SIFAT OBJEK
12.1
Pendahuluan
Salah satu ciri dari OOP yang sebelumnya telah kita singgung pada bab sebelumnya adalah kemampuan suatu objek atau kelas untuk mewariskan sifat-sifat yang terdapat di dalamnya ke kelas turunannya. Hal ini dinamakan dengan inheritance. Konsep ini kelihatannya mudah, tapi sebenarnya banyak detil tersembunyi yang harus diperhatikan. Walaupun demikian, hal yang paling utama ditekankan dalam proses penurunan sebuah kelas adalah pemberian hak akses terhadap kelas-kelas turunan. Bahasa C + + merupakan bahasa pemrograman yang mendukung penuh tentang konsep-konsep OOP sehingga di dalamnya juga banyak terdapat fitur yang tersedia untuk proses penurunan sebuah kelas yang harus dipelajari. Pada bagian ini kita akan membahas semua hal tersebut secara rinci melalui contoh-contoh program.
12.2
Kelas Dasar dan Kelas Turunan
Kelas dasar yang dimaksud di sini adalah sebuah kelas yang akan dijadikan sebagai induk dari kelas lain. Kelas dasar ini masih lebih dikenal dengan istilah dalam bahasa asing, yaitu Jbase class. Sedangkan kelas baru yang merupakan hasil dari proses penurunan Pemrograman C++
Bab 12: Pewarisan Sifat Objek
tersebut disebut dengan kelas turunan, atau sering juga disebut dengan derived class. Dalam mempelajari materi ini sebenarnya sama seperti mempelajari ilmu biologi yang membahas tentang klasifikasi sebuah tumbuhan. Dalam ilmu biologi, suatu tumbuhan berasal dari suatu kelas (tipe) tertentu sehingga tumbuhan tersebut akan mewarisi sifat-sifat yang terdapat pada kelas pendahulunya. Begitupun dalam program, suatu kelas dapat dijadikan sebagai kelas dasar (induk) untuk kemudian diturunkan menjadi kelas-kelas selanjutnya. Misalnya terdapat kelas A yang diturunkan menjadi kelas B, selanjutnya kelas B diturunkan lagi menjadi kelas C, begitu seterusnya. Di sini, kelas B dan kelas C tentu akan memiliki sifat-sifat yang terdapat pada kelas A. Begitu juga kelas C, pasti akan mewarisi sifat-sifat yang terdapat pada kelas B. Secara umum, di dalam C + + , penurunan sebuah kelas dapat dilambangkan dengan gambar di bawah ini.
kelas dasar. Berikut ini bentuk umum dari pembuatan sebuah kelas turunan di dalam C + + . class nama__kelas_turunant hak_akses naoa_kelas__dasar { // data-data dan fungsi-fungsi
Agar dapat lebih memahaminya, perhatikan contoh program berikut dimana di dalamnya terdapat pendefinisian sebuah kelas turunan. Kode Program 12-1 #include
using namespace std;
// Membuat kelas dasar dengan nama INDUK class INDUK { int X; public : void SetX(int XX) { X = XX; } int GetXO { return X?
// Membuat kelas turunan dengan nama TURUNAN class TURUNAN: public INDUK { int Y; public: void SetY(int YY) { Y = YY;
Seperti yang kita lihat di atas bahwa sebuah kelas dasar dapat diturunkan menjadi beberapa kelas yang berbeda. Selanjutnya masing-masing kelas turunan tersebut dapat diturunkan lagi menjadi kelas-kelas turunan berikutnya, begitu seterusnya.
int GetYO { return Y;
// Fungsi utama int main() {
•// Melakukan instansiasi terhadap kelas INDUK •INDUK A;
12.3
Membuat Kelas Turunan
// Memanggil fungsi-fungsi milik kelas INDUK dari kelas INDL A.SetX(12);
Untuk membuat sebuah kelas turunan sebenarnya sama seperti pada saat kita membuat kelas-kelas biasa, perbedaannya hanya di sini terdapat pendefinisian nama kelas yang akan dijadikan sebagai Pemrograman C++
cout«"Nilai X yang dipanggil dari kelas INDUK cout«A . GetX ( ) «endl ; cout«' \n' ;
Bab 12: Pewarisan Sifat Objek
I
/ MelatitlESirTnstansia^^prhadap *4^Br 'URUNAN B;
turunan juga dapat menjadi induk dari kelas-kelas yang lainnya. Berikut ini program yang menunjukkan hal tersebut.
kelas TURUNAN
Kode Program 12-2
// Melakukan pemanggilan fungsi-fungsi // yang terdapat pada kelas TURUNAN B.SetY(40);
tinclude
cout<<"Nilai Y yang terdapat pada kelas TURUNAN : cout«B. GetY () «endl ; cout«' \n' ;
v
ti-fungsi milik kelas INDUK dari kelas // Tl B.set cout«"Nilai X yang dipanggil dari kelas TURUNAN : "; cout«B.GetX()«end
using namespace std; // Membuat kelas dasar dengan nama INDUK class INDUK { int X; public: void SetX (int XX) { X = XX; int GetX() { return X;
return
Hasil yang akan diberikan dari program di atas adalah sebagai berikut: Nilai X yang dipanggil dari kelas INDUK
: 12
Nilai Y yang terdapat pada kelas TURUNAN : 40
// Membuat kelas turunan dari kelas INDUK dengan nama TURUNAN1 class TURUNAN1: public INDUK { int Y; public : void SetY(int YY) { Y = YY; } int GetYO { return Y;
Nilai X yang dipanggil dari kelas TURUNAN : 35 Dari hasil di atas dapat kita simpulkan bahwa kelas TURUNAN telah mewarisi sifat-sifat yang dimiliki oleh kelas INDUK. Sebagai bukti pernyataan ini, di atas kita dapat menggunakan fungsi SetX ( ) dan GetX() di dalam objek B yang merupakan instance dari kelas TURUNAN. Sedangkan apabila kita amati, fungsi-fungsi tersebut adalah milik dari kelas INDUK. Sebenarnya, setelah proses penurunan kelas di atas, kelas INDUK akan mewariskan fungsi SetX ( ) dan GetX ( ) kepada kelas TURUNAN, ini berarti bahwa sekarang kelas TURUNAN juga telah mempunyai fungsi yang bernama SetX ( ) dan GetX ( ) . Dalam program, hal inilah yang dinamakan dengan konsep pewarisan sifat objek. Pada program di atas, kita baru melakukan satu kali proses penurunan. Sekarang kita akan mem'buktikan bahwa sebuah kelas Pemrograman C++
// Membuat kelas turunan dari kelas TURUNANl // TURUNAN2 class TURUNAN2: public TURUNANl { int Z; public: void SetZ(int ZZ) { Z = ZZ;
dengan nama
int GetZO { return Z;
// Fungsi utama int main() { // Melakukan instansiasi terhadap kelas TURUNAN2 TURUNAN2 A;
Bab 12: Pewarisan Sifat Objek
// Melakukan pengesetan nilai X, Y dan Z melalui kelas // TURUNAN2 A.SetX{20); A.SetY(30); A.SetZ(40); // Menampilkan nilai X, Y dan cout«"Nilai X yang dipanggil cout«A. GetX () «endl ; cout«"Nilai Y yang dipanggil cout«A. GetY () «endl ; cout«"Nilai Z yang dipanggil cout«A. GetZ () «endl ;
• •
Bagian public yang terdapat pada kelas induk tetap akan menjadi bagian public pada kelas turunannya. Bagian protected yang terdapat pada kelas induk tetap akan menjadi bagian protected pada kelas turunannya. Bagian private yang terdapat pada kelas induk tetap tidak dapat diakses oleh kelas turunannya.
Z melalui kelas TURUNAN2 dari kelas TURUNAN2 : ";
•
dari kelas TURUNAN2 : ";
Apabila kelas diturunkan sebagai private dari kelas induknya, maka: • Bagian public yang terdapat pada kelas induk akan menjadi bagian private pada kelas turunannya. • Bagian protected yang terdapat pada kelas induk akan menjadi bagian private pada kelas turunannya. • Bagian private yang terdapat pada kelas induk tetap tidak dapat diakses oleh kelas turunannya.
dari kelas TURUNAN2 :
return 0;
Hasil yang akan diberikan dari program di atas adalah sebagai berikut:
Berikut ini contoh program di atas yang dituliskan kembali. Maksudnya adalah untuk menjelaskan konsep pembuatan kelas yang diturunkan sebagai public oleh kelas induknya.
Nilai X yang dipanggil dari kelas TURUNAN2 : 20 Nilai Y yang dipanggil dari kelas TURUNAN2 : 30 Nilai Z yang dipanggil dari kelas TURUNAN2 : 40
Kode Program 12-3 Hasil di atas memmjukkan bahwa kelas TURUNAN2 akan memiliki fungsi-fungsi yang dimiliki oleh kelas induknya (kelas TURUNAN1), yaitu fungsi SetY ( ) dan GetY ( ) . Namun perlu diperhatikan, di sini kelas TURUNAN1 adalah turunan dari kelas INDUK, maka dari itu secara otomatis kelas TURUNAN2 juga akan memiliki fungsifungsi yang dimiliki oleh kelas INDUK, yaitu fungsi SetX ( ) dan GetX ( ) . Walaupun demikian, sebuah kelas turunan tetap tidak dapat mewarisi data atau fungsi-fungsi yang bersifat private pada kelas induknya.
12.4
Hak Akses pada Proses Pewarisan
Dalam proses penurunan sebuah kelas, kita harus benar-benar pandai dalam memberikan hak akses data atau fungsi terhadap kelas turunan. Berikut ini hal-hal yang perlu Anda ketahui dalam membuat sebuah kelas turunan. Apabila kelas diturunkan sebagai public dari kelas induknya, maka : Pemrograman C++
tinclude using namespace std; // Membuat kelas dasar dengan nama INDUK class INDUK { int X; public: void SetX{int XX) { X = XX; } int GetX() { return X;
// Membuat kelas TURUNANl yang diturunkan sebagai public // dari kelas INDUK class TURUNANl: public INDUK { int Y; public: void SetY(int YY) { Y = YY; int GetYO { return Y; Bab 12: Pewarisan Sifat Objek
buah fungsi yang bersifat public (yaitu fungsi SetZ ( ) , GetZ ( ) , SetY ( ) , GetY ( ) , SetX ( ) dan GetX ( ) ) . Itulah sebabnya pada program di atas kita dapat mengakses fungsi-fungsi yang terdapat pada kelas INDUK dan kelas TURUNANl melalui suatu objek (instance) dari kelas TURUNAN2.
// Membuat kelas TURUNAN2 yang diturunkan // dari kelas TURUNANl Class TURUNAN2: public TURUNANl { int Z; public: void SetZ(intZZ) { , Z = ZZ; j int GetZ() { return Z;
Sekarang kita akan mencoba untuk membuat suatu kelas yang diturunkan sebagai private dari kelas induknya, yaitu dengan cara memodifikasi program di atas. Adapun sintaks programnya adalah sebagai berikut: Kode Program 12-4 #include
// Fungsi utama int main() { // Melakukan in TURUNAN2 A;
using namespace std; terhadap kelas TURUNAN2
//Melakukan pengesetan nilai X, Y dan Z melalui kelas // TURUNAN2 A.SetX(20) ; A.SetY(30); A. SetZ(40); // Menampilkan nilai X, Y dan cout«"Nilai X yang dipanggil cout«A. GetX {) «endl ; cout« "Nilai Y yang dipanggil cout«A.GetY () «endl ,cout«"Nilai Z yang dipanggil cout«A. GetZ () «endl ;
Z melalui kelas TURUNAN2 dari kelas TURUNAN2 : "; dari kelas TURUNAN2 : "; dari kelas TURUNAN2 : ";
// Membuat kelas dasar dengan nama INDUK class INDUK { int X; public: void SetX(int XX) { X = XX; } int GetX{) { return X;
// Membuat kelas TURUNANl yang diturunkan sebagai private // dari kelas INDUK class TURUNANl: private INDUK { int Y; public: void SetY(int YY) { Y = YY; int GetY() { return Y;
return
Apabila kita analisis program di atas, bagian public dari kelas INDUK (yaitu fungsi SetX ( ) dan GetX ( ) ) tetap akan menjadi bagian public pada kelas TURUNANl, sedangkan variabel X yang terdapat pada bagian private tetap tidak dapat diakses oleh kelas TURUNANl. Sampai di sini, berarti kelas TURUNANl telah mempunyai empat buah fungsi yang bersifat public (yaitu fungsi S e t Y O , G e t Y ( ) , S e t X ( ) dan GetX ( ) ) . Selanjutnya kelas TURUNANl akan diturunkan lagi secara public terhadap kelas TURUNAN2. Hal ini menyebabkan bagian public yang terdapat pada kelas TURUNANl akan diwariskan semuanya kepada kelas TURUNAN2 sehingga kelas TURUNAN2 akan mempunyai enam Pemrograman C++
// Membuat kelas TURUNAN2 yang diturunkan sebagai private // dari kelas TURUNANl class TURUNAN2: private TURUNANl { int Z; public: void SetZ(int ZZ) { Z = ZZ; int GetZ() { return Z;
Bab 12: Pewarisan Sifat Objek
kelas C tentu akan mewarisi sifat-sifat yang terdapat pada kelas A dan kelas B.
'gsi u tama ini :'na // Melakukan instansiasi terhadap kelas TURUNAN2 TURUNAN2 A; // Melakukan pengesetan nilai X, Y dan Z melalui kelas // TURUNAN2 A.SetX(20); // SALAH, tidak diizinkan oleh compiler A.SetY(30); // SALAH, tidak diizinkan oleh compiler A.SetZ(40);
Sebenarnya kita bisa juga melakukannya dengan proses yang berulang, yaitu dengan menurunkan kelas A menjadi kelas B, kemudian baru menurunkan kelas B menjadi kelas C. Namun hal ini tentu akan memakan waktu yang cukup lama dibandingkan kita menurunkannya dari beberapa induk secara langsung. Berikut ini gambar yang akan mengilustrasikan proses multiple inheritance.
.;// Statesmen di bawah ini SALAH, karena mengakses bagian // private cout« "Nilai X yang dipanggil dari kelas TURUNAN2 cout«A.GetX()«endl;
Kelas_ .Indukl
Kelas_ Indukl
Kelas_IndukN
t
i
('
// Statemen di bawah ini SALAH, karena mengakses bagian // private cout«"Nilai Y yang dipanggil dari kelas TURUNAN2 cout«A.GetY( ) «endl ; cout« "Nilai Z yang dipanggil dari kelas TURUNAN2 cout«A . GetZ { ) «endl ;
KelasJ'urunan
Adapun bentuk umum dari pembuatan kelas melalui proses multiple inheritance adalah sebagai berikut : class nama^kelas turunan: hak akses nama_kelas_induklf hak_akses nama__kelas_induk2 , hak_akses nama_kelas_indukN
Program di atas tidak dapat dijalankan, karena terdapat beberapa kesalahan di dalamnya. Apabila kita analisis, bagian public dari kelas INDUK tentu akan menjadi bagian private pada kelas TURUNAN1, sedangkan bagian public dari kelas TURUNAN1 akan menjadi bagian private pada kelas TURUNAN2. Hal inilah yang menyebabkan kesalahan pada program di atas karena terdapat usaha untuk mengakses bagian private dari suatu kelas.
{
// data-data dan fwagsi-fungsi
Berikut ini contoh program yang mengimplementasikan konsep di atas. Kode Program 12-5 #include
12.5
using namespace std;
Multiple Inheritance
Salah satu kelebihan dari C++ dibandingkan bahasa-bahasa pemrograman lain yang juga mendukung OOP adalah karena C + + mendukung adanya multiple inheritance. Adapun multiple inheritance yang dimaksud di sini adalah suatu proses pembuatan kelas baru dimana kelas tersebut diturunkan dari dua kelas induk atau lebih. Sebagai contoh, kita memiliki kelas A dan B yang masing-masing berdiri sendiri. Kemudian kita ingin membuat kelas C yang merupakan turunan dari kelas A dan B. Dengan demikian, Pemrograman C++
// Membuat kelas dengan nama INDUK1 class INDUK1 { int X; publi c: void SetXfint XX) { X = XX; int GetXO { return X;
Bab 12: Pewarisan Sifat Objek
// Membuat kelas dengan nama INDUK2 y«3g tidak berkaitan //dengan kelas INDUK1 class INDUK2 { int Y; public: void SetY(int YY) { Y = YY;
Seperti yang kita lihat di atas bahwa kelas TURUNAN akan memiliki fungsi-fungsi yang terdapat di bagian public atau protected pada kelas-kelas induknya. Pada contoh ini, fungsi-fungsi yang akan dimiliki oleh kelas TURUNAN adalah fungsi SetX ( ) , GetX ( ) , S e t Y ( ) , G e t Y ( ) , S e t Z ( ) dan G e t Z ( ) .
int GetYO { return Y;
12.6
};
// Membuat kelas TURUNAN yang merupakan turunan // dari kelas INDUK1 dan INDUK2 class TURUNAN: public INDUKl, public INDUK2 { int Z; public: void SetZ(int ZZ) { Z = ZZ;
Pada bab sebelumnya kita telah mempelajari bagaimana membuat fungsi constructor untuk suatu kelas dasar. Sebenarnya tidak terdapat perbedaan sintaks antara constructor pada kelas dasar dan kelas turunan. Namun, hal yang perlu diperhatikan adalah: apabila kita ingin melakukan inisialisasi nilai yang terdapat pada kelas induk melalui constructor kelas turunan, maka kita dapat memanggil constructor kelas induk tersebut dari dalam constructor kelas turunan. Perhatikan contoh potongan sintaks berikut: class INDUK {
int GetZO { return ZZ;
int X; public; // constructor kelas INDUK INDUK(int XX) { X = XX;
// Fungsi utama int main() { // Melakukan instansiasi terhadap kelas TURUNAN TURUNAN A; // Memanggil fungsi-fungsi yang terdapat pada kelas TURUNAN A.S.etX(lOO) ; A.SetY(200); A.SetZOOO) ; // Menampikan ni <.ai yang telah diset
cout«"Nilai X cout«"Nilai Y cout«"Nila^fc!Sl
: "«A.GetX()«endl; : "«A.GetY( )«endl; : "«A.GetZO;
return 0 ;
Apabila dijalankan, program di atas akan memberikan hasil seperti di bawah ini. Nilai X Nilai Y Nilai Z
Constructor pada Proses Penurunan Kelas
: 100 :200 :300
// fungsi lain . . . }; . ,.
Selanjutnya, apabila kita ingin melakukan inisialisasi terhadap nilai X di atas dari sebuah kelas turunan (misalkan dengan nama TURUNAN), maka kita dapat memanggil constructor kelas INDUK pada saat kita membuat constructor kelas TURUNAN, seperti yang terlihat pada sintaks berikut: class TURUNAN: public INDUK { int Y; public: // constructor kelas TURUNAN TURUNAN(int XX, int YY) { INDUK(XX); // memanggil constructor kelas Y = YY; // mengeset nilai Y
// fungsi lain .,. Kode di atas dapat juga dituliskan seperti berikut: Pemrograman C++
Bab 12: Pewarisan Sifat Objek
INDUK^
. cout«"Nilai Y : "«A.GetY()
class TURUNAN: public INDUK { int Y;
return 0;
public: // constructor kelas TURUNAN TURUNAN(int XX, int YY) : INDUK(XX) { Y = YY; // mengeset nilai Y
Hasil yang akan diberikan dari program di atas adalah sebagai berikut:
} // fungsi lain ...
Berikut ini contoh program yang menunjukkan bagaimana cara membuat constructor pada kelas turunan. Kode Program 12-6
Constructor kelas INDUK Constructor kelas TURUNAN Nilai X : 10 Nilai Y : 20 Apabila kita analisis hasil di atas, pada saat sebuah objek turunan dibuat di dalam memori, maka sebenarnya akan dibuat kelas induk terlebih dahulu.
ttinclude using namespace std; class INDUK { int X; public : // Constructor pada kelas INDUK INDUK (int XX) { X = XX; cput« "Constructor kelas INDUK "<<endl;
Sekarang, apabila kita akan membuat suatu constructor pada kelas yang diturunkan melalui proses multiple inheritance, maka kita akan menyebutkan constructor dari semua kelas induknya. Berikut ini contoh program yang akan menunjukkan hal tersebut.
I
Kode Program 12-7
'.// Membuat fungsi GetX int GetXO { return X;
tinclude using namespace std; // Membua t kelas INDUKl class INDUKl { int X; public: // Constructor pada kelas INDUKl INDUKl(int XX) { X = XX; cout«"Constructor kelas INDUKl"«endl } // Membuat fungsi GetX int GetXO { return X;
class TURUNAN: public INDUK { int Y;
public: // Constructor pada kelas TURUNAN TURUNAN(int XX, int Y Y ) : INDUK(XX) {
Y = YY; cout«"Constructor kelas TURUNAN"«endl; // Membuat fungsi GetY int GetYO { return Y;
// Membuat kelas INDUK2 class INDUK2 { int Y; public: // Constructor pada kelas INDUK2 !NDUK2(int YY) { !;' Y = YY; cout«"Constructor kelas INDUK2"«endl,
// Fungsi utama int m a i n ( ) { // Melakukan instansiasi terhadap kelas TURUNAN TURUNAN A(10, 2 0 ) ; // Melakukan pemanggilan fungsi melalui objek A cout«"Nilai X : "«A.GetX ( ) «endl ;
Pemrograman CM
Bab 12: Pewarisan Sifat Objek
// M int GetY() { return Y;
BAB 13 VIRTUAL DAN POLIMORFISME
gsi GetY
// Membuat Jcelas TURUNAN // yang diturunkan dri kelas INDUK1 dan INDUK2 class TURUNAN: public INDUK1, public INDUK2 { int Z; public: // Constructor pada kelas TURUNAN TURUNANfint XX, int YY, int ZZ) : INDUKl(XX), INDUK2(YY) Z = ZZ;
cout«"Constructor kelas TURUNAN" «endl; } // Membuat fungsi GetZ int GetZO { return Z;
// Fungsi utama int main() { .// Melakukan instansiasi terhadap kelas TURUNAN A(10, 20, 3 0 ) ; // Melakukan cout«"Nilai cout«"Nilai COUt«"Nilai
13.1
TURUNAN
pemanggilan fungsi melalui objek A X : "«A.GetX ( ) «endl; Y : "«A.GetY() «endl; Z : "«A.GetZ();
return 0;
;
Apabila dijalankan, program di atas akan memberikan hasil sebagai berikut: Constructor kelas INDUK1 Constructor kelas INDUK2 Constructor kelas TURUNAN Nilai X : 10 Nilai Y : 20 Nilai Z : 30
Pendahuluan
Polimorfisme merupakan ciri OOP yang keempat setelah abstraksi, pembungkusan atau pengkapsulan dan pewarisan (inheritance). Pada bagian ini kita akan membahas tentang apa yang dimaksud dengan polimorfisme dan implementasinya dalam pembuatan kelas di dalam C + + . Namun, sebelum itu kita akan membahas mengenai hal yang mutlak diperlukan dalam mempelajari polimorfisme terlebih dahulu, yaitu fungsi virtual.
13.2
Fungsi Virtual
Fungsi virtual adalah fungsi yang mendukung adanya polymorphic function, artinya fungsi tersebut dapat didefinisikan ulang pada kelas-kelas turunannya. Fungsi virtual ini biasanya terdapat pada kelas-kelas dasar. Walaupun demikian, kita juga dapat mendeklarasikan fungsi virtual pada kelas-kelas turunan yang akan dijadikan sebagai kelas dasar bagi kelas-kelas lainnya. Dalam C+ + , untuk mendefinisikan fungsi sebagai fungsi virtual adalah dengan Pemrograman
Bab 13: Virtual dan Polimorfisme
menggunakan kata kunci virtual, yaitu dengan menempatkannya di depan pendeklarasian fungsi tersebut. Pendefinisian fungsi virtual yang terdapat pada kelas dasar biasanya tidak begitu berarti, artinya kode-kode yang terdapat di dalamnya masih bersifat general. Selanjutnya setiap kelas turunan akan mendefinisikan ulang fungsi virtual itu dengan mengisikan perintah-perintah yang sudah spesifik sesuai dengan kebutuhan dari kelas turunan tersebut. Untuk lebih memahaminya berikut ini contoh pembuatan sebuah fungsi virtual yang terdapat dalam kelas dasar. class MANUSIA { char* nama; int tinggi; int berat; public: void SetNama(char* N) { nama = N;
13.3
Override
Seperti yang telah dikemukakan di atas bahwa fungsi virtual dapat didefinisikan ulang pada kelas turunannya. Hal ini tentu memungkinkan untuk terjadinya proses pembaharuan dari definisi suatu fungsi. Dalam OOP, proses pembaharuan tersebut disebut dengan istilah override. Untuk lebih jelasnya, perhatikan contoh program di bawah ini. Kode Program 13-1 #include using namespace std; class MANUSIA { char * nama; int tinggi; int berat; public: void SetNama(char* N) { nama = N;
void SetTinggi(int T) { tinggi = T; void SetBerat(int B) { berat = B;
void SetTinggi(int T) { tinggi = T;
(
char* GetNamaO { return nama;
void SetBerat(int berat = B;
int GetTinggi() { return tinggi;
char* GetNamaO { return nama;
int GetBerat() { return berat;
int GetTinggi() { return tinggi ,-
// Membuat fungsi virtual virtual void BerjalanO { cout«"Ber jalan"«endl ;
int GetBeratO { return berat;
virtual void Berpakaian() { cout« "Berpakaian" «endl
// Membuat fungsi virtual virtual void BerjalanO { cout«"Berjalan"«endl;
Seperti yang kita lihat di atas bahwa kita telah membuat dua buah fungsi virtual, yaitu fungsi BerjalanO dan Berpakaian(). Fungsi-fungsi ini selanjutnya dapat didefinisikan ulang dengan implementasi yang berbeda pada setiap kelas turunannya.
Pemrograman C++
virtual void Berpakaian() { cout«" Berpakaian" «endl
class MAHASISWA: public MANUSIA { char* universitas; char* jurusan; Bab 13: Virtual dan Polimorfisme
int semester; iblic : void SetUniversitas (c universitas = U;
// Fungsi utama int main() {
void Set Jurusan{ char* J) { jurusan = J; } void SetSemester (int smt) { semester = smt; } char* GetUnlversitas () { return universitas; } char* GetJurusanO { return jurusan; } int GetSemesterO { return semester;
//Melakukan instansiasi terhadap kelas MANUS MANUSIA M; // Melakukan instansiasi terhadap kelas MAHASISWA MAHASISWA MHS; // Melakukan instansiasi terhadap kelas TENTARA TENTARA TTR; // Memanggil fungsi Berjalan dari masing-masing keli M.BerjalanO ; MHS.BerjalanO ; TTR.BerjalanO ; cout«' \n' ;
// Melakukan override terhadap fungsi Berjalan void BerjalanO ( cout«"Berjalan dengan cara SANTAI"«endl;
// Memanggil fungsi Berpakaian dari masing-masing kelai M.Berpakaian(); MHS. Berpakaian (); TTR. Berpakaian ();
// Melakukan override terhadap fungsi Berpakaian void Berpakaian() { cout«"Berpakaian dengan baju BEBAS"«endl;
return 0;
Apabila dijalankan, hasil yang akan diberikan dari program di atas adalah sebagai berikut:
class TENTARA: public MANUSIA { char* pangkat; char* kesatuan; public : void Set Pangkat (char* pkt) { pangkat = pkt; } void SetKesatuan(char* kstn) { kesatuan = kstn; } schar* GetPangkatO { return pangkat; } char* GetKesatuan ( ) { return kesatuan;
Berjalan Berjalan dengan cara SANTAI Berjalan dengan cara TEGAP Berpakaian Berpakaian dengan baju BEBAS Berpakaian dengan baju SERAGAM
// Melakukan override terhadap fungsi Berjalan void Berjalan( ) { cout«"Berjalan dengan cara TEGAP"«endl; } // Melakukan override terhadap fungsi Berpakaian void Berpakaian ( ) { cout«"Berpakaian dengan baju SERAGAM"«endl;
Pemrograman
Dari hasil di atas dapat kita amati bahwa dengan mendefinisikan fungsi BerjalanO sebagai fungsi virtual, kita dapat melakukan override terhadap fungsi tersebut. Di atas, fungsi BerjalanO akan diimplementasikan berdasarkan kelas masing-masing, begitu juga dengan fungsi Berpakaian ( ) .
Bab 13: Virtual dan Polimorfisme
13.4
Perbedaan Override dengan Overload
Terdapat kemiripan istilah antara override dan overload. Anda tidak perlu bingung karena keduanya memang dua hal yang sangat berbeda. Pada proses override kita tidak dapat mengubah parameter dari fungsi (yang didefinisikan sebagai fungsi virtual) yang terdapat pada kelas induk, baik itu tipe data ataupun jumlah dari parameter tersebut. Sedangkan overload adalah pembuatan fungsi-fungsi dengan nama sama tetapi jumlah parameter dari fungsi-fungsi tersebut berbeda Dengan demikian, override bukanlah overload. Agar dapat lebih menyerap konsep yang ada, berikut ini contoh program yang akan membedakan kedua istilah di atas. Kode Program 13-2
// Membuat kelas PROGRAMMER yang diturunkan dari kelas KARYAl class PROGRAMMER: public KARYAWAN { double bonus; public: // Melakukan overload pada fungsi constructor kelas // PROGRAMMER PROGRAMMER() { bonus = 0; |PROGRAMMER(double bns) { bonus = bns; fdouble GetBonus() { return bonus; j// Melakukan override terhadap fungsi Bekerja yoid Bekerja() { cout«"Bekerja dengan cara membuat program " \ "menggunakan komputer"; cout«endl;
#include using namespace std; class GURU: public KARYAWAN { char* MateriAjar; public: void SetMateriAjar(char* MA) { MateriAjar = MA; } char* GetMateriAjar() { return MateriAjar;
Class KARYAWAN { char* NIP; char* nama; double GajiPokok; public: void SetNIPfchar* Nolnduk) { NIP = Nolnduk; } void SetNama(char* run) { nama = nm; } void SetGajiPokok(double GP) { GajiPokok = GP;
// Melakukan override terhadap fungsi Bekerja void Bekerja() { cout«"Bekerja dengan cara mengajar di depan kelas' cout«' \n' ;
char* GetNIPO { return NIP; har* GetNamaO return nama;
// Fungsi utama int main() {
{
// Melakukan instansiasi terhadap kelas PROGRAMMER // dengan mengeset bonus sebesar 1000000 PROGRAMMER P(IOOOOOO);
ouble GetGajiPokok() { return GajiPokok;
// Melakukan instansiasi terhadap kelas GURU GURU G;
// Membuat fungsi virtual virtual void Bekerja() { cout«"Bekerja"«endl ;
// Memanggil fungsi bekerja untuk kelas PROGRAMMER dan GURU P.BekerjaO ; G.Bekerj a();
Pemrograman C++
Bab 13: Virtual dan Polimorfisme
ablic:
Hasil yang akan diperoleh dari program di atas adalah sebagai berikut: Bekerja dengan cara membuat program menggunakan komputer Bekerja dengan cara mengajar di depan kelas Perhatikan proses contructor pada kelas PROGRAMMER di atas, di situ terdapat proses overload terhadap fungsi constructor. Fungsi contructor dibuat dua kali, yaitu dengan menggunakan parameter dan tanpa parameter. Sedangkan yang dimaksud dengan override pada program di atas adalah pendefinisian fungsi Beker j a ( ) yang terdapat pada kelas PROGRAMMER dan kelas GURU.
13.5
Fungsi Virtual Murni (Pure Virtual Function)
Setelah mengetahui definisi fungsi virtual, maka di sini kita akan membahas mengenai fungsi virtual murni atau yang lebih dikenal dengan pure virtual function. Adapun yang dimaksud dengan fungsi virtual murni adalah fungsi yang murni tidak mempunyai definisi sama sekali. Artinya fungsi tersebut baru didefinisikan pada kelas turunannya. Dalam C+ + , untuk mendefinisikan fungsi sebagai fungsi virtual murni adalah dengan cara mengisikan nilai 0 ke dalam fungsi tersebut. Berikut ini bentuk umum pembuatan sebuah fungsi virtual murni. virtual tipe_data nana^fungsifparameter1, parameter^ ...; = Q; Berikut ini contoh program yang menunjukkan pembuatan fungsi virtual murni dalam sebuah kelas dasar. Kode Program 13-3
/// Membuat fungsi virtual murni, ___. •?// artinya tanpa definisi/impleme^S^i [^virtual void BerjalanO » 0; [virtual void BerpakaianO = 0; ivoid SetNama(char* N) { nama = N; [xvoid SetTinggi (int T) { tinggi = T; |cvoid SetBerat(int B) { berat = B; Jihar* GetNama () { return nama; | int GetTinggi() { return tinggi; [lint GetBerat () { return berat;
class MAHASISWA: public MANUSIA { char* universitas; char* jurusan; int semester; public: void SetUniversitas(char* U) { universitas = U; } void SetJurusan(char* J) { jurusan = J; } void SetSemester(int smt) { semester = smt; [char* GetUniversitas() { return universitas; jchar* GetJurusan() { return jurusan;
^include |int GetSemester() { return semester; • } >^ // Mendefinisikan fungsi Berjalan untuk kelas MAHASISWA void BerjalanO { cout«"Mahasiswa berjalan dengan cara SANTAI"«endl;
using namespace s NUSIA { class MANUSIA char riarna; int ti nggi "int be
T.
Pemrograman
Bab 13: Virtual dan Polimorfisme
// Mendefinisikan fungsi Berpakaian untuk kelas MAHASISWA void Berpakaian() { cout«"Mahasiswa berpakaian dengan baju BEBAS"«endl;
Mahasiswa berjalan dengan cara SANTAI Tentara berjalan dengan cara TEGAP Mahasiswa berpakaian dengan baju BEBAS Tentara berpakaian dengan baju SERAGAM
class TENTARA: public MANUSIA { char* pangkat ,char* kesatuan; public: void SetPangkat(char* pkt) { pangkat = pkt;
Seperti yang kita lihat di atas bahwa fungsi B e r j a l a n O dan Berpakaian () hanya mempunyai implementasi pada kelas turunannya saja (kelas MAHASISWA dan TENTARA), sedangkan pada kelas dasar (kelas MANUSIA), fungsi-fungsi tersebut tidak mempunyai implementasi sama sekali.
void SetKesatuan(char* kstn) { kesatuan = kstn; char* GetPangkat() { return pangkat; char* GetKesatuanf) { return kesatuan;
13.6
// Mendefinisikan fungsi Berjalan untuk kelas TENTARA void BerjalanO { cout«"Tentara berjalan dengan cara TEGAP"«endl; // Mendefinisikan fungsi Berpakaian untuk kelas TEA void Berpakaian() { cout«"Tentara berpakaian dengan baju SERAGAM"«€
// Fungsi utama int main{} {
Virtual Dectructor
C++ merupakan bahasa yang mendukung adanya virtual destructor pada sebuah kelas. Hal ini bertujuan untuk menghindari terjadinya memory leak. Apabila kita mempunyai sebuah pointer yang bertipe kelas induk, dan pointer tersebut ditunjukkan ke kelas turunan, maka pada saat kita menghapus pointer tersebut, yang akan terhapus dari memori hanyalah objek induknya saja, sedangkan objek turunannya sebenarnya masih terdapat di dalam memori. Kita tentu tidak menginginkan hal ini terjadi bukan? Untuk lebih memahaminya perhatikan contoh program di bawah ini dimana kita menggunakan destructor bias a (bukan virtual). Kode Program 13-4
//; Melakukan instansiasi terhadap kelas TENTARA TENTARA T;
ttinclude
// Memanggil fungsi Berjalan dari masing-masing kelas M.BerjalanO ; T.BerjalanO ; cout«endl ; // Memanggil fungsi Berpakaian dari masing-masing kelas M. Berpakaian . Berpakaian ();
using namespace std; class INDUK { public: -INDUK() { cout«"Destructor kelas INDUK"«endl;
rn 0;
Hasil yang akan diberikan dari program di atas adalah sebagai berikut: Pemrograman
class TURUNAN: public INDUK { public: -TURUNAN() { cout«"Destructor kelas TURUNAN"«endl
Bab 13: Virtual dan Polimorfisme
// Mendeklarasikan pointer yang bertipe kelas INDUK INDUK *PI;. // Fungsi utama int main() {
// Mengalokasikan ruang untuk menempatkan objek TURUNAN PI = new TURUNAN;
// Mendeklarasikan pointer yang bertipe kelas INDUK INDUK *PI; // Mengalokasikan ruang untuk menempatkan objek TURUNAN PI = new TURUNAN; // Menghapus pointer PI delete PI;
// Menghapus pointer PI delete PI; return 0;
Sekarang, apabila program tersebut dijalankan, maka hasil yang akan diberikan adalah sebagai berikut:
return 0;
Hasil yang akan diberikan dari program di atas adalah sebagai berikut: Destructor kelas INDUK Seperti yang terlihat di atas bahwa objek dari kelas TURUNAN tidak ikut didestruksi. Maka dari itu, pada kasus ini kita harus menggunakan virtual destructor pada kelas induk. Adapun sintaks programnya akan berubah menjadi seperti di bawah ini.
Destructor kelas TURUNAN Destructor kelas INDUK Mungkin Anda bingung kenapa program akan mendestruksi kelas TURUNAN terlebih dahulu? Jawabnya mudah, dalam pemrograman, setiap constructor sebuah objek, maka program akan melakukan constructor terhadap induk dari objek tersebut terlebih dahulu. Sedangkan untuk destructor, merupakan kebalikan dari proses constructor. Artinya yang akan dihapus terlebih dahulu dari memori adalah objek turunannya, baru kemudian objek-objek induknya.
Kode Program 13-5 tinclu.de
13.7
using namespace std;
Kelas Abstrak
Kelas abstrak adalah sebuah kelas yang mempunyai fungsi virtual murni di dalamnya. Maka dari itu kita juga tidak diizinkan untuk melakukan instansiasi dari kelas abstrak. Sebenarnya pada program-program di atas, secara tidak langsung kita sudah membuat kelas abstrak, namun kita akan membahasnya lebih detil pada sub bab ini. Berikut ini contoh program yang tidak diizinkan.
class INDUK { public: // Membuat virtual destructor virtual -INDUK() { cout«"Destructor kelas INDUK"«endl;
tihclude using namespace std; Class KARYAWAN { public: virtual void Bekerjaf
Pemrograman
Bab 13: Virtual dan Polimorfisme
Lass PROGR xLic: void BekerjaO { cout«"Bekerja dengan cara membu : "menggunakan komputer" ,cout«endl;
class GURU: public KARYAWAN { public: void Bekerja() { cout«"Bekerja dengan cara mengajar di depan kelas cout«endl ;
KARYAWAN, sehingga untuk mengakses fungsi Beker j a ( ) yang terdapat pada kelas-kelas turunan (kelas PROGRAMMER dan GURU), terpaksa kita harus tetap melakukan instansiasi terhadap kelaskelas turunan tersebut. Hal ini tentu tidak efisien, maka dari itu C++ menyediakan suatu cara untuk dapat mengakses fungsifungsi di dalam kelas turunan hanya dengan mendeklarasikan sebuah pointer yang bertipe kelas induk. Selanjutnya pointer tersebut akan dapat menunjuk ke tipe-tipe kelas turunan yang ada. Sebagai contoh, perhatikan contoh program di bawah ini dimana di dalamnya terdapat adanya konsep polimorfisme. Kode Program 13-7 ftinclude
//- Fungsi utama int main {) { // Melakukan instansiasi terhadap kelas KARYAWAN KARYAWAN A; // SALAH, tidak diizinkan oleh kompiler // Melakukan instansiasi terhadap kelas PROGRAMMER PROGRAMMER B; // Melakukan instansiasi terhadap kelas GURU GURU C;
Apabila program di atas dijalankan maka akan terdapat error, karena pada program tersebut terdapat instansiasi dari kelas abstrak, yaitu kelas KARYAWAN.
13.8
using namespace std; class KARYAWAN { public : virtual void BekerjaO =
Class PROGRAMMER: publ i C KARYAWAN { ublic : void Beker ja{) { cout«"Bekerja dengan cara membuat program ; "menggunakan komputer"; cout«endl;
r
w
\
class GURU: public KARYAWAN { public : void Beker ja( ) { c out«" Beker j a dengan cara mengajar di depan kelas"; cout«endl ;
Polimorfisme
Setelah pembahasan-pembahasan di atas sekarang kita akan menginjak ke pembahasan pokok pada bab ini, yaitu polimorfisme, yang merupakan salah satu ciri utama dari OOP. Secara definisi, polimorfisme dapat diartikan sebagai kemampuan mengungkap suatu hal yang berbeda melalui satu cara yang sama. Untuk mengetahui konsep yang terdapat di dalamnya, perhatikan kembali program di atas (pada sub bab kelas abstrak). Pada program tersebut kita tidak dapat melakukan instansiasi pada kelas Pemrograman C++
// Fungsi utama int main() { // Mendeklarasikan pointer yang bertipe kelas KARYAWAN KARYAWAN *P; P = new PROGRAMMER; P->Bekerja(); delete P;
// Menghapus pointer P
Bab 13: Virtual dan Polimorfisme
// yang menunjuk ke tipe
PROGRAMMER
P = new GURU; P->Bekerja();
return 0; Apabila dijalankan, program di atas akan memberikan hasil seperti yang tampak di bawah ini. Bekerja dengan cara membuat program menggunakan komputer Bekerja dengan cara mengajar di depan kelas Coba Anda amati program di atas. Pada program tersebut kita hanya melakukan pendeklarasian pointer terhadap kelas KARYAWAN (yang merupakan kelas induk), namun kita dapat mengakses fungsi-fungsi yang terdapat di dalam kelas PROGRAMMER dan kelas GURU (yang merupakan kelas-kelas turunan). Perhatikan juga statemen srjaO; Dengan menggunakan statemen tersebut, kita dapat mengungkap dua hal yang berbeda. Hal ini tentu tergantung dari nilai P yang ada pada waktu itu. Artinya, jika P sedang menunjuk ke tipe PROGRAMMER, maka statemen di atas akan mengakses fungsi Beker j a ( ) yang terdapat pada kelas PROGRAMMER. Sebaliknya jika P menunjuk ke tipe GURU, maka yang akan diakses adalah fungsi Bekerja() yang terdapat dalam kelas GURU. Hal itulah yang menyebabkan statemen di atas dapat memberikan hasil yang berbeda. Konsep seperti inilah yang dinamakan dengan polimorfisme.
Pemrograman
BAGIAN III PEMROGRAMAN TINGKAT LANJUT