Bab. 4 Pewarisan
Tujuan
Instruksional
|
|
·
Kelas basis dan
kelas terderivasi.
·
Anggota protected.
·
Relasi antara kelas
basis dan kelas terderivasi.
|
·
Konstruktor dan
destruktor di dalam kelas terderivasi.
·
Pewarisan public, private, dan protected.
|
4.1 Introduksi
Bab ini akan melanjutkan diskusi
tentang pemrograman berorientasi objek dengan mengenalkan konsep pewarisan.
Pewarisan merupakan suatu bentuk pendaur-ulangan kode dimana di dalamnya Anda
dapat menciptakan suatu kelas yang menyerap kapabilitas-kapabilitas yang
dimiliki oleh kelas yang sudah ada, kemudian memperbaikinya untuk tujuan Anda.
Pendaur-ulangan kode dapat menghemat waktu dalam pengembangan program dengan
mengambil keuntungan dari kelas yang sudah teruji dan berkualitas tinggi.
Ketika menciptakan sebuah kelas,
daripada menulis anggota data dan anggota fungsi yang baru, Anda bisa
menciptakan kelas baru yang mewarisi anggota-anggota dari kelas yang sudah ada.
Kelas yang sudah ada ini disebut dengan kelas basis, dan kelas baru yang
mewarisi tersebut dikenal dengan kelas terderivasi. Bahasa pemrograman lain
seperti Java dan C# menyebutkan kelas basis sebagai superkelas dan kelas
terderivasi sebagai subkelas. Kelas terderivasi merepresentasikan grup-grup
objek yang lebih spesifik.
C++ menawarkan pewarisan public, protected, dan private. Pada
bab ini, akan dikonsentrasikan untuk membahas pewarisan public dan hanya menjelaskan secara singkat tentang dua jenis
pewarisan yang lain. Dengan pewarisan public,
setiap objek dari kelas terderivasi merupakan objek dari kelas basis yang
diwarisi oleh kelas terderivasi tersebut.
Tetapi, sebaliknya, objek kelas basis bukan merupakan objek dari kelas
terderivasinya. Sebagai contoh, jika Anda memiliki Kendaraan sebagai kelas basis dan Mobil sebagai kelas terderivasinya, maka semua Mobil adalah Kendaraan,
tetapi tidak semua Kendaraan adalah Mobil, karena Kendaraan bisa juga berupa Truk,
Becak, Motor, dan lainnya.
Gambar
4.1 Beberapa contoh pewarisan
Kelas Basis
|
Kelas Terderivasi
|
Mahasiswa
Bangun
Pinjaman
Karyawan
Akun
|
MahasiswaSarjana, MahasiswaPascaSarjana
Lingkaran, SegiTiga, PersegiPanjang, Kubus
PinjamanPeruhaman, PinjamanMobil, PijamanMultiGuna
Fakultas, Staf
AkunSimpanan, AkunPinjaman
|
Anda perlu membedakan antara relasi
adalah-suatu dan relasi memiliki-suatu. Relasi adalah-suatu merepresentasikan
pewarisan. Di dalam relasi adalah-suatu, sebuah objek dari kelas terderivasi
dapat juga diperlakukan sebagai objek kelas basis. Sebagai contoh, sebuah Mobil adalah sebuah Kendaraan, jadi sembarang atribut dan watak dari Kendaraan juga merupakan atribut dan
watak dari Mobil. Kebalikannya,
relasi adalah-suatu merepresentasikan komposisi. Di dalam relasi adalah-suatu,
sebuah objek memuat satu atau lebih objek dari kelas lain sebagai anggota.
Sebagai contoh, sebuah Mobil memiliki
banyak komponen, seperti Ban, Rem, dan lainnya.
4.2 Kelas Basis dan Kelas Terderivasi
Gambar 4.1 mencantumkan beberapa contoh
sederhana dari kelas basis dan kelas terderivasi. Kelas basis cenderung lebih
umum dan kelas terderivasi cenderung lebih spesifik. Karena setiap objek kelas
terderivasi merupakan objek kelas basisnya, dan satu kelas basis dapat memiliki
banyak kelas terderivasi, maka himpunan objek yang direpresentasikan oleh kelas
basis umumnya lebih besar atau lebih umum dari himpunan objek yang
direpresentasikan oleh sembarang kelas terderivasinya. Sebagai contoh, kelas
basis Kendaraan merepresentasikan
semua kendaraan, termasuk mobil, truk, pesawat, sepeda, dan lainnya.
Kebalikannya, kelas terderivasi Mobil
merepresentasikan subhimpunan yang lebih kecil dan lebih spesifik.
Relasi pewarisan membentuk hirarki
kelas. Sebuah kelas basis memiliki relasi hirarkis dengan kelas-kelas
terderivasinya. Meskipun masing-masing kelas dapat eksis secara independen, begitu
kelas tersebut diterapkan di dalam relasi pewarisan, maka ia menjadi
terafiliasi dengan kelas-kelas lain. Kelas basis
Hirarki Kelas
AnggotaKomunitas
Sekarang akan dikembangkan hirarki
pewarisan lima level (yang direpresentasikan oleh diagram kelas UML pada Gambar
4.2). Komunitas universitas memiliki ribuan AnggotaKomunitas.
AnggotaKomunitas memuat Karyawan, Mahasiswa, dan Alumnus. Karyawan bisa memuat Fakultas dan Staf. Fakultas bisa
memuat Pengelola dan Dosen. Beberapa Pengelola juga bisa merupakan Dosen.
Digunakan pewarisan jamak untuk membentuk kelas PengelolaDosen. Dengan pewarisan tunggal, sebuah kelas diderivasi
hanya dari satu kelas basis. Dengan pewarisan jamak, sebuah kelas terderivasi
mewarisi satu atau lebih kelas basis.
Setiap panah di dalam hirarki (Gambar
4.2) merepresentasikan relasi adalah-suatu. Sebagai contoh, bila diikuti arah
panah dalam hirarki kelas, Anda dapat menyatakan bahwa “suatu Karyawan adalah suatu AnggotaKomunitas” dan “suatu Dosen adalah suatu anggota Fakultas”. AnggotaKomunitas merupakan kelas basis langsung bagi Karyawan, Mahasiswa, dan Alumnus.
Selain itu, AnggotaKomunitas adalah
kelas basis tak-langsung bagi semua kelas lain dalam diagram.
Gambar 4.2 Hirarki pewarisan untuk AnggotaKomunitas
Hirarki Kelas
Bangun
Sekarang perhatikan hirarki pewarisan Bangun pada Gambar 4.3. Hirarki ini
dimulai dengan kelas basis Bangun.
Kelas BangunDuaDimensi dan BangunTigaDimensi diderivasi dari kelas
basis Bangun. Level ketiga dari
hirarki ini memuat tipe yang lebih spesifik dari BangunDuaDimensi dan dari BangunTigaDimensi.
Sama seperti pada Gambar 4.2, Anda dapat mengikuti panah dari bawah diagram ke
arah atas sampai kelas basis teratas di dalam hirarki ini untuk
mengidentifikasi beberapa relasi adalah-suatu. Misalnya, suatu SegiTiga adalah suatu BangunDuaDimensi dan adalah suatu Bangun, sedangkan suatu Tabung adalah suatu BangunTigaDimensi dan adalah suatu Bangun.
Gambar 4.3 Hirarki pewarisan Bangun
Untuk menspesifikasi bahwa kelas BangunDuaDimensi (Gambar 4.3) diderivasi
dari (mewarisi dari) kelas Bangun,
definisi kelas BangunDuaDimensi harus
dimulai dengan:
class BangunDuaDimensi :
public Bangun
Ini merupakan contoh pewarisan public, yang paling umum digunakan.
Nanti pada gilirannya akan didiskusikan perihal pewarisan private dan pewarisan protected.
Pada pewarisan public, anggota public kelas basis menjadi anggota public kelas terderivasi, dan anggota protected kelas basis menjadi anggota protected kelas terderivasi.
4.3 Anggota protected
Anggota public suatu kelas basis dapat diakses dari dalam tubuh kelas
tersebut dan dari tempat manapun yang dapat dilakukan program (misalnya lewat
nama, referensi, atau pointer) di dalam kelas basis tersebut atau dari salah
satu kelas terderivasinya.Anggota private
suatu kelas basis dapat diakses dari dalam tubuh kelas tersebut dan oleh friend dari kelas basis tersebut. Pada
bagian ini, akan dikenalkan penspesifikasi akses protected. Penggunaan akses protected
menawarkan level proteksi menengah antara akses public dan private.
Anggota protected suatu kelas basis
dapat diakses dari dalam tubuh kelas basis tersebut, oleh anggota dan friend dari kelas basis tersebut, dan
oleh anggota dan friend dari
sembarang kelas yang diderivasi dari kelas basis tersebut.
Fungsi anggota kelas terderivasi dapat
merujuk ke anggota protected dan public dari kelas basisnya hanya dengan
menggunakan nama anggota. Ketika sebuah fungsi anggota kelas terderivasi
mendefinisikan-ulang fungsi anggota kelas basis, maka fungsi anggota kelas
basis tersebut masih bisa diakses dari kelas terderivasi dengan memberikan
prefiks berupa nama anggota kelas basis dengan nama kelas basis dan operator
resolusi skop (::).
4.4 Relasi Antara Kelas Basis dan Kelas
Terderivasi
Pada bagian ini, Anda akan menggunakan hirarki
pewarisan yang memuat beberapa tipe karyawan di dalam aplikasi penggajian
perusahaan untuk mendiskusikan relasi antara kelas basis dan kelas terderivasi.
Karyawan komisi (yang direpresentasikan sebagai objek kelas basis) dibayar
berdasarkan persentasi penjualan, sedangkan karyawan komisi bergaji pokok (yang
direpresentasikan sebagai objek kelas terderivasi dibayar berdasarkan gaji
pokok dan persentase penjualan. Selanjutnya diskusi ini akan dibagi menjadi
karyawan komisi dan karyawan komisi bergaji pokok dalam lima contoh ke depan.
4.4.1 Menciptakan dan Menggunakan Kelas
KaryawanKomisi
Sekarang akan diperiksa definisi kelas KaryawanKomisi (Gambar 4.4 – 4.5).
Header KaryawanKomisi (Gambar 4.4)
menspesifikasi layanan public dari kelas KaryawanKomisi,
yang menyertakan sebuah konstruktor (baris 12-13) dan fungsi anggota penghasilan (baris 30) dan tampil (baris 31). Baris 15-28
mendeklarasikan beberapa fungsi get
dan set (public) yang memanipulasi anggota-anggota data kelas
(dideklarasikan pada baris 33-37) namaPertama,
namaAkhir, nomorKTP, penjualanKotor,
dan besarKomisi. Fungsi anggota setPenjualanKotor (didefinisikan pada
baris 56-62, Gambar 4.5) dan setBesarKomisi
(didefinisikan pada baris 71-77, Gambar 4.5) dipakai untuk memvalidasi
argumen-argumennya sebelum menugaskan nilai-nilai kepada anggota-anggota data penjualanKotor dan besarKomisi.
Gambar 4.4 Definisi Kelas KaryawanKomisi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// Gambar 4.4: KaryawanKomisi.h
// Definisi kelas KaryawanKomisi
merepresentasikan seorang karyawan komisi.
#ifndef KOMISI_H
#define KOMISI_H
#include <string> // Kelas string standard C++
using namespace std;
class KaryawanKomisi
{
public:
KaryawanKomisi(
const string &, const string &, const string
&,
double
= 0.0, double = 0.0 );
void setNamaPertama( const
string & ); // menetapkan nama pertama
string getNamaPertama() const; //
mengembalikan nama pertama
void setNamaAkhir( const
string & ); // menetapkan nama akhir
string getNamaAkhir() const; //
mengembalikan nama akhir
void setNomorKTP( const string
& ); // menetapkan nomor KTP
string getNomorKTP() const; //
mengembalikan nomor KTP
void setPenjualanKotor( double
); // menetapkan jumlah penjualan kotor
double getPenjualanKotor() const;
// mengembalikan jumlah penjualan kotor
void setBesarKomisi( double ); //
menetapkan besar komisi (persentase)
double getBesarKomisi() const;
// mengembalikan besar komisi
double penghasilan() const; //
menghitung penghasilan
void tampil() const; //
menampilkan objek KaryawanKomisi
private:
string
namaPertama;
string
namaAkhir;
string
nomorKTP;
double
penjualanKotor; // penjualan kotor mingguan
double
besarKomisi; // persentasi komisi
}; // akhir dari kelas KaryawanKomisi
#endif
|
Gambar 4.5 Definisi Fungsi Anggota Kelas
KaryawanKomisi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
// Gambar 4.5: KaryawanKomisi.cpp
// Definisi fungsi anggota kelas
KaryawanKomisi.
#include <iostream>
#include "KaryawanKomisi.h" // definisi
kelas KaryawanKomisi
using namespace std;
// konstruktor
KaryawanKomisi::KaryawanKomisi(
const string
&pertama, const string &akhir, const string &ktp,
double penjualan, double
komisi )
{
namaPertama
= pertama; // seharusnya divalidasi
namaAkhir
= akhir; // seharusnya divalidasi
nomorKTP
= ktp; // seharusnya divalidasi
setPenjualanKotor(
penjualan ); // memvalidasi dan menyimpan penjualan kotor
setBesarKomisi(
komisi ); // memvalidasi dan menyimpan besar komisi
} // akhir dari konstruktor KaryawanKomisi
// menetapkan nama pertama
void KaryawanKomisi::setNamaPertama( const
string &pertama )
{
namaPertama = pertama; // seharusnya
divalidasi
} // akhir dari fungsi setNamaPertama
// mengembalikan nama pertama
string KaryawanKomisi::getNamaPertama() const
{
return namaPertama;
} // akhir dari fungsi getNamaPertama
// menetapkan nama akhir
void KaryawanKomisi::setNamaAkhir( const string
&akhir )
{
namaAkhir = akhir; // seharusnya divalidasi
} // akhir dari fungsi setNamaAkhir
// mengembalikan nama akhir
string KaryawanKomisi::getNamaAkhir() const
{
return namaAkhir;
} // akhir dari fungsi getNamaAkhir
// menetapkan nomor kartu penduduk
void KaryawanKomisi::setNomorKTP( const string
&ktp )
{
nomorKTP = ktp; // seharusnya divalidasi
} // akhir dari fungsi setNomorKTP
// mengembalikan nomor kartu penduduk
string KaryawanKomisi::getNomorKTP() const
{
return nomorKTP;
} // akhir dari fungsi getNomorKTP
// menetapkan jumlah penjualan kotor
void KaryawanKomisi::setPenjualanKotor( double
penjualan )
{
if ( penjualan >= 0.0 )
penjualanKotor = penjualan;
else
throw invalid_argument( "penjualan
kotor harus >= 0.0" );
} // akhir dari fungsi setPenjualanKotor
// menghasilkan jumlah penjualan kotor
double KaryawanKomisi::getPenjualanKotor() const
{
return penjualanKotor;
} // akhir dari fungsi penjualanKotor
// menetapkan besar komisi
void KaryawanKomisi::setBesarKomisi( double
komisi )
{
if ( komisi > 0.0 &&
komisi < 1.0 )
besarKomisi = komisi;
else
throw invalid_argument( "besar
komisi harus di antara > 0.0 dan < 1.0" );
} //
akhir dari fungsi setBesarKomisi
// mengembalikan besar komisi
double KaryawanKomisi::getBesarKomisi() const
{
return besarKomisi;
} // akhir dari fungsi getBesarKomisi
// menghitung penghasilan
double KaryawanKomisi::penghasilan() const
{
return
besarKomisi * penjualanKotor;
} // akhir dari fungsi penghasilan
// menampilkan objek KaryawanKomisi
void KaryawanKomisi::tampil() const
{
cout
<< "karyawan komisi: " << namaPertama << '
' << namaAkhir
<<
"\nnomor kartu penduduk: " << nomorKTP
<<
"\npenjualan kotor: " << penjualanKotor
<<
"\nbesar komisi: " << besarKomisi;
} // akhir dari fungsi tampil
|
Konstruktor
KaryawanKomisi
Definisi konstruktor KaryawanKomisi tidak menggunakan sintaks
penginisialisasi anggota di dalam beberapa contoh ke depan, sehingga Anda dapat
mendemonstrasikan bagaimana penspesifikasi private dan protected mempengaruhi
akses anggota di dalam kelas terderivasi. Seperti yang ditunjukkan pada Gambar 4.5,
baris 12-14, nilai-nilai ditugaskan kepada anggota-anggota data namaPertama, namaAkhir, dan nomorKTP
di dalam tubuh konstruktor. Selanjutnya pada bagian ini, kembali akan digunakan
daftar penginisialisasi anggota di dalam konstruktor.
Fungsi Anggota
penghasilan dan tampil pada Kelas KaryawanKomisi
Fungsi anggota penghasilan (baris 86-89) menghitung penghasilkan KaryawanKomisi. Baris 88 mengalikan besarKomisi dengan penjualanKotor dan memberikan nilai balik hasil perkalian tersebut.
Fungsi anggota tampil (baris 92-98)
menampilkan nilai-nilai anggota daya objek KaryawanKomisi.
Menguji Kelas
KaryawanKomisi
Gambar 4.6 menguji kelas KaryawanKomisi. Baris 11-12
menginstansiasi objek karyawan dari
kelas KaryawanKomisi dan memanggil
konstruktor KaryawanKomisi untuk
menginisialisasi objek tersebut dengan “Adam”
sebagai nama pertama, “Napitupulu”
sebagai nama akhir, “222-22-2222” sebagai nomor KTP, 10000 sebagai jumlah
penjualan kotor, dan .06 sebagai besar komisi. Baris 19-24 menggunakan beberapa
fungsi get (dari objek karyawan) untuk menampilkan nilai-nilai
anggota data. Baris 26-27 memanggil fungsi anggota setPenjualanKotor dan setBesarKomisi
untuk mengubah nilai-nilai anggota data penjualanKotor
dan besarKomisi. Baris 31 kemudian
memanggil fungsi anggota tampil untuk
menampilkan informasi KaryawanKomisi
yang telah diperbarui. Terakhir, baris 34 menampilkan penghasilan KaryawanKomisi, dihitung menggunakan
fungsi anggota penghasilan dengan
nilai-nilai anggota data penjualanKotor
dan besarKomisi yang telah
diperbarui.
Gambar 4.6 Menguji Kelas KaryawanKomisi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// Gambar 4.6: gambar4_06.cpp
// Menguji kelas KaryawanKomisi.
#include <iostream>
#include <iomanip>
#include "KaryawanKomisi.h" // definisi
kelas KaryawanKomisi
using namespace std;
int main()
{
//
menginstansiasi suatu objek KaryawanKomisi
KaryawanKomisi
karyawan(
"Adam",
"Napitupulu", "222-22-2222", 10000, .06 );
//
menetapkan fotmat keluaran pecahan
cout << fixed << setprecision( 2
);
// mendapatkan data karyawan komisi
cout << "Informasi karyawan
didepatkan dengan fungsi get: \n"
<< "\nNama pertama adalah "
<< karyawan.getNamaPertama()
<< "\nNama akhir adalah "
<< karyawan.getNamaAkhir()
<< "\nNomor kartu penduduk
adalah "
<< karyawan.getNomorKTP()
<< "\nPenjualan kotor adalah
" << karyawan.getPenjualanKotor()
<< "\nBesar komisi adalah "
<< karyawan.getBesarKomisi()
<< endl;
karyawan.setPenjualanKotor(
8000 ); // menetapkan penjualan kotor
karyawan.setBesarKomisi(
.1 ); // mentepakan besar komisi
cout << "\nInformasi
karyawan terperbarui ditampilkan dengan fungsi tampil: \n"
<< endl;
karyawan.tampil();
// menampilkan informasi karyawan yang baru
// menampilkan penghasilan karyawan
cout << "\n\nPenghasilan
karyawan: Rp. " << karyawan.penghasilan() << endl;
} //
akhir dari main
|
Informasi karyawan didepatkan dengan fungsi get:
Nama pertama adalah Adam
Nama akhir adalah Napitupulu
Nomor kartu penduduk adalah 222-22-2222
Penjualan kotor adalah 10000.00
Besar komisi adalah 0.06
Informasi karyawan terperbarui ditampilkan dengan fungsi
tampil:
karyawan komisi: Adam Napitupulu
nomor kartu penduduk: 222-22-2222
penjualan kotor: 8000.00
besar komisi: 0.10
Penghasilan karyawan: Rp. 800.00
4.4.2 Menciptakan Kelas
KaryawanKomisiPlusPokok Tanpa Pewarisan
Sekarang akan didiskusikan bagian
menciptakan dan menguji (kelas yang baru dan independen) kelas KaryawanKomisiPlusPokok (Gambar 4.7 – 4.8),
yang memuat nama pertama, nama akhir, nomor KTP, jumlah penjualan kotor, besar
komisi, dan gaji pokok.
Gambar 4.7 Definisi Kelas KaryawanKomisiPlusPokok
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
// Gambar 4.7: KaryawanKomisiPlusPokok.h
// Definisi kelas
KaryawanKomisiPlusPokok merepresentasikan seorang karyawan komisi
// yang menerima gaji pokok selain komisi.
#ifndef POKOK_PLUS_H
#define POKOK_PLUS_H
#include <string> // Kelas string standard C++
using namespace std;
class KaryawanKomisiPlusPokok
{
public:
KaryawanKomisiPlusPokok( const string
&, const string &, const string &,
double = 0.0, double = 0.0, double = 0.0 );
void setNamaPertama( const
string & ); // menetapkan nama pertama
string getNamaPertama() const; //
mengembalikan nama pertama
void setNamaAkhir( const
string & ); // menetapkan nama akhir
string getNamaAkhir() const; // mengembalikan
nama akhir
void setNomorKTP( const string
& ); // menetapkan nomor KTP
string getNomorKTP() const; //
mengembalikan nomor KTP
void setPenjualanKotor( double
); // menetapkan jumlah penjualan kotor
double getPenjualanKotor() const;
// mengembalikan jumlah penjualan kotor
void setBesarKomisi( double );
// menetapkan besar komisi (persentase)
double getBesarKomisi() const;
// mengembalikan besar komisi
void setGajiPokok( double ); // menetapkan gaji
pokok
double getGajiPokok() const; // mengembalikan gaji
pokok
double penghasilan() const; //
menghitung penghasilan
void tampil() const; //
menampilkan objek KaryawanKomisiPlusPokok
private:
string namaPertama;
string namaAkhir;
string nomorKTP;
double penjualanKotor; // penjualan
kotor mingguan
double besarKomisi; // persentasi
komisi
double gajiPokok; // gaji pokok
}; // akhir dari kelas
KaryawanKomisiPlusPokok
#endif
|
Gambar 4.8 Definisi Fungsi Anggota Kelas
KaryawanKomisiPlusPokok
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
// Gambar 4.8: KaryawanKomisiPlusPokok.cpp
// Definisi fungsi anggota kelas
KaryawanKomisiPlusPokok.
#include <iostream>
#include "KaryawanKomisiPlusPokok.h" // definisi kelas KaryawanKomisiPlusPokok
using namespace std;
// konstruktor
KaryawanKomisiPlusPokok::KaryawanKomisiPlusPokok(
const
string &pertama, const string &akhir, const string
&ktp,
double
penjualan, double komisi, double gaji )
{
namaPertama
= pertama; // seharusnya divalidasi
namaAkhir = akhir; // seharusnya divalidasi
nomorKTP = ktp; // seharusnya divalidasi
setPenjualanKotor( penjualan ); // memvalidasi dan
menyimpan penjualan kotor
setBesarKomisi( komisi ); // memvalidasi dan menyimpan besar komisi
setGajiPokok( gaji ); //
memvalidasi dan menyimpan gaji pokok
} // akhir dari konstruktor
KaryawanKomisiPlusPokok
// menetapkan nama pertama
void KaryawanKomisiPlusPokok::setNamaPertama( const
string &pertama )
{
namaPertama = pertama; // seharusnya divalidasi
} // akhir dari fungsi setNamaPertama
// mengembalikan nama pertama
string
KaryawanKomisiPlusPokok::getNamaPertama() const
{
return
namaPertama;
} // akhir dari fungsi getNamaPertama
// menetapkan nama akhir
void KaryawanKomisiPlusPokok::setNamaAkhir( const
string &akhir )
{
namaAkhir = akhir; // seharusnya divalidasi
} // akhir dari fungsi setNamaAkhir
// mengembalikan nama akhir
string
KaryawanKomisiPlusPokok::getNamaAkhir() const
{
return
namaAkhir;
} // akhir dari fungsi getNamaAkhir
// menetapkan nomor kartu penduduk
void KaryawanKomisiPlusPokok::setNomorKTP(
const
string &ktp )
{
nomorKTP = ktp; // seharusnya divalidasi
} // akhir dari fungsi setNomorKTP
// mengembalikan nomor kartu penduduk
string
KaryawanKomisiPlusPokok::getNomorKTP() const
{
return
nomorKTP;
} // akhir dari fungsi getNomorKTP
// menetapkan jumlah penjualan kotor
void KaryawanKomisiPlusPokok::setPenjualanKotor( double
penjualan )
{
if
( penjualan >= 0.0 )
penjualanKotor = penjualan;
else
throw
invalid_argument( "penjualan kotor harus >= 0.0" );
} // akhir dari fungsi setPenjualanKotor
// menghasilkan jumlah penjualan kotor
double KaryawanKomisiPlusPokok::getPenjualanKotor() const
{
return
penjualanKotor;
} // akhir dari fungsi penjualanKotor
// menetapkan besar komisi
void KaryawanKomisiPlusPokok::setBesarKomisi( double
komisi )
{
if
( komisi > 0.0 && komisi < 1.0 )
besarKomisi = komisi;
else
throw
invalid_argument( "besar komisi harus di antara > 0.0 dan < 1.0"
);
} //
akhir dari fungsi setBesarKomisi
// mengembalikan besar komisi
double KaryawanKomisiPlusPokok::getBesarKomisi() const
{
return
besarKomisi;
} // akhir dari fungsi getBesarKomisi
// menetapkan gaji pokok
void KaryawanKomisiPlusPokok::setGajiPokok( double
gaji )
{
if
( gaji >= 0.0 )
gajiPokok
= gaji;
else
throw
invalid_argument( "Gaji pokok harus >= 0.0" );
} // akhir dari fungsi setGajiPokok
// mengembalikan gaji pokok
double KaryawanKomisiPlusPokok::getGajiPokok() const
{
return
gajiPokok;
} // akhir dari fungsi getGajiPokok
// menghasilkan penghasilan
double KaryawanKomisiPlusPokok::penghasilan() const
{
return
gajiPokok + ( besarKomisi * penjualanKotor );
} // akhir dari fungsi penghasilan
// menampilkan objek KaryawanKomisiPlusPokok
void KaryawanKomisiPlusPokok::tampil() const
{
cout << "karyawan
komisi bergaji pokok: " <<
namaPertama << ' '
<<
namaAkhir << "\nnomor kartu penduduk: " <<
nomorKTP
<< "\npenjualan kotor: "
<< penjualanKotor
<< "\nbesar komisi: "
<< besarKomisi
<< "\ngaji pokok: " << gajiPokok;
} // akhir dari fungsi tampil
|
Mendefinisikan
Kelas KaryawanKomisiPlusPokok
Header KaryawanKomisiPlusPokok (Gambar 4.7) menspesifikasi layanan public dari kelas KaryawanKomisiPlusPokok, yang menyertakan konstruktor KaryawanKomisiPlusPokok (baris 13-14)
dan fungsi anggota penghasilan (baris
34) dan tampil (baris 35). Baris
16-32 mendeklarasikan beberapa fungsi get
dan set untuk anggota-anggota data private (dideklarasikan pada baris
37-42) namaPertama, namaAkhir, nomorKTP, penjualanKotor,
besarKomisi, dan gajiPokok. Semua variabel dan fungsi anggota merupakan fitur
penting untuk karyawan komisi bergaji pokok. Perhatikan kesamaan kode ini
dengan kode kelas KaryawanKomisi
(Gambar 4.4 – 4.5).
Fungsi anggota penghasilan dari kelas KaryawanKomisiPlusPokok
(didefinisikan pada baris 100-103 pada Gambar 4.8) menghitung penghasilan
karyawan komisi bergaji pokok. Baris 102 memberikan nilai balik berupa hasil
penjumlahan dari gaji pokok dengan gaji karyawan komisi.
Menguji Kelas
KaryawanKomisiPlusPokok
Gambar 4.9 menguji kelas KaryawanKomisiPlusPokok. Baris 11-12
menginstansiasi objek karyawan dari
kelas KaryawanKomisiPlusPokok, dengan
melewatkan “Rotua”, “Marolop”, “333-33-3333”, 5000, .04, dan
300 kepada konstruktor sebagai nama pertama, nama akhir, nomor kartu penduduk,
penjualan kotor, besar komisi, dan gaji pokok. Baris 19-25 menggunakan beberapa
fungsi get untuk mengambil
nilai-nilai anggota data objek untuk ditampilkan. Baris 27 memanggil fungsi
anggota setGajiPokok untuk mengubah
besaran gaji pokok. Fungsi anggota setGajiPokok
(Gambar 4.8, baris 88-94) memastikan bahwa anggota data gajiPokok tidak ditugasi nilai negatif, karena gaji pokok karyawan
tidak bisa bernilai negatif. Baris 31 pada Gambar 4.9 memanggil fungsi anggota tampil untuk menampilkan informasi KaryawanKomisiPlusPokok yang telah
diperbarui, dan baris 34 memanggil fungsi anggota penghasilkan untuk menampilkan penghasilan KaryawanKomisiPlusPokok.
Gambar 4.9 Definisi Kelas KaryawanKomisiPlusPokok
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// Gambar 4.9: gambar4_09.cpp
// Menguji kelas KaryawanKomisiPlusPokok.
#include <iostream>
#include <iomanip>
#include "KaryawanKomisiPlusPokok.h"
using namespace std;
int main()
{
//
menginstansiasi objek KaryawanKomisiPlusPokok
KaryawanKomisiPlusPokok
karyawan( "Rotua",
"Marolop", "333-33-3333", 5000, .04, 300 );
// menetapkan format keluaran pecahan
cout << fixed << setprecision( 2
);
// mendapatkan data karyawan komisi
cout << "Informasi karyawan
didapatkan dengan fungsi-fungsi get: \n"
<< "\nNama pertama adalah "
<< karyawan.getNamaPertama()
<< "\nNama akhir adalah "
<< karyawan.getNamaAkhir()
<< "\nNomor kartu penduduk
adalah "
<< karyawan.getNomorKTP()
<< "\nPenjualan kotor adalah
" << karyawan.getPenjualanKotor()
<< "\nBesar komisi adalah "
<< karyawan.getBesarKomisi()
<< "\nGaji pokok adalah " <<
karyawan.getGajiPokok() << endl;
karyawan.setGajiPokok( 1000 ); // menetapkan gaji pokok
cout << "\nInformasi
karyawan terperbarui ditampilkan oleh fungsi tampil: \n"
<< endl;
karyawan.tampil(); //
menampilkan informasi karyawan yang baru
// menampilkan penghasilan karyawan
cout << "\n\nPenghasilan
karyawan: Rp. " << karyawan.penghasilan() <<
endl;
} // akhir dari main
|
Informasi karyawan didapatkan dengan fungsi-fungsi get:
Nama pertama adalah Rotua
Nama akhir adalah Marolop
Nomor kartu penduduk adalah 333-33-3333
Penjualan kotor adalah 5000.00
Besar komisi adalah 0.04
Gaji pokok adalah 300.00
Informasi karyawan terperbarui ditampilkan oleh fungsi
tampil:
karyawan komisi bergaji pokok: Rotua Marolop
nomor kartu penduduk: 333-33-3333
penjualan kotor: 5000.00
besar komisi: 0.04
gaji pokok: 1000.00
Penghasilan karyawan: Rp. 1200.00
Mengeksploarasi Kesamaan Kelas
KaryawanKomisiPlusPokok dan Kelas KaryawanKomisi
Hampir semua kode untuk kelas KaryawanKomisiPlusPokok (Gambar 4.7 - 4.8)
sama, bahkan hampir identik, dengan kode untuk kelas KaryawanKomisi (Gambar 4.4 – 4.5). Sebagai contoh, dalam kelas KaryawanKomisiPlusPokok, anggota-anggota
data private namaPertama dan namaAkhir
dan fungsi-fungsi anggota setNamaPertama,
getNamaPertama, setNamaAkhir, dan getNamaAkhir
identik dengan yang ada pada kelas KaryawanKomisi.
Kelas KaryawanKomisiPlusPokok dan KaryawanKomisi juga sama-sama memuat
anggota-anggota data private nomorKTP, besarBonus, dan penjualanKotor,
berikut dengan beberapa fungsi get
dan set untuk memanipulasi
anggota-anggota tersebut. Selain itu, konstruktor KaryawanKomisiPlusPokok identik dengan konstruktor kelas KaryawanKomisi, kecuali bahwa
konstruktor KaryawanKomisiPlusPokok
juga menetapkan gajiPokok. Tambahan
lain pada kelas KaryawanKomisiPlusPokok
adalah anggota data private, gajiPokok, dan fungsi anggota setGajiPokok dan getGajiPokok. Fungsi anggota tampil
pada kelas KaryawanKomisiPlusPokok
hampir identik dengan yang ada pada kelas KaryawanKomisi,
kecuali bahwa tampil pada kelas KaryawanKomisiPlusPokok menampilkan juga
anggota data gajiPokok.
Secara literal, Anda bisa menyalin
kelas KaryawanKomisi ke dalam KaryawanKomisiPlusPokok, kemudian
memodifikasinya untuk menyertakan gaji pokok dan beberapa fungsi anggota untuk
memanipulasi gaji pokok. Pendekatan salin-dan-tempel ini sangat rentan terhadap
kesalahan dan cukup memakan waktu.
4.4.3 Menciptakan Hirarki Pewarisan KaryawanKomisi-KaryawanKomisiPlusPokok
Sekarang akan diciptakan dan diuji
suatu kelas KaryawanKomisiPlusPokok
yang baru (Gambar 4.10 – 4.11) yang mewarisi dari kelas KaryawanKomisi (Gambar 4.4 – 4.5). Pada contoh ini, suatu objek KaryawanKomisiPlusPokok adalah sebuah
objak KaryawanKomisi (karena
pewarisan mewariskan kapabilitas dari kelas KaryawanKomisi),
tetapi kelas KaryawanKomisiPlusPokok
juga memiliki anggota data gajiPokok
(Gambar 4.10, baris 23). Titik-dua (:) pada baris 11 di dalam definisi kelas mengindikasikan
pewarisan. Katakunci public
mengindikasikan tipe pewarisan. Sebagai kelas terderivasi (dibentuk dengan
pewarisan public), KaryawanKomisiPlusPokok mewarisi semua
anggota kelas KaryawanKomisi, kecuali
konstruktor, karena setiap kelas menyediakan konstruktornya sendiri yang
spesifik dengan kelas tersebut (destruktor juga tidak diwarisi). Jadi, layanana
public dari kelas KaryawanKomisiPlusPokok mencakup
konstruktornya (baris 14-15) dan beberapa fungsi anggota public yang diwarisi dari kelas KaryawanKomisi.
Meskipun Anda tidak bisa melihat semua fungsi yang diwarisi di dalam kode
sumber KaryawanKomisiPlusPokok,
tetapi semua fungsi tersebut adalah bagian dari kelas terderivasi KaryawanKomisiPlusPokok. Layanan public dari kelas terderivasi juga mencakup
beberapa fungsi anggota setGajiPokok,
getGajiPokok, penghasilan, dan tampil
(baris 17-21).
Gambar 4.10 Definisi
Kelas KaryawanKomisiPlusPokok Mengindikasikan Relasi Pewarisan dengan Kelas
KaryawanKomisi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// Gambar 4.10: KaryawanKomisiPlusPokok.h
// Kelas KaryawanKomisiPlusPokok diderivasi
dari kelas
// KaryawanKomisi.
#ifndef POKOK_PLUS_H
#define POKOK_PLUS_H
#include <string> // Kelas string standard C++
#include "KaryawanKomisi.h"
using namespace std;
class KaryawanKomisiPlusPokok : public
KaryawanKomisi
{
public:
KaryawanKomisiPlusPokok(
const string &, const string &,
const
string &, double = 0.0, double = 0.0, double = 0.0
);
void
setGajiPokok( double ); // menetapkan gaji pokok
double
getGajiPokok() const; // mengembalikan gaji pokok
double
penghasilan() const; // menghitung penghasilan
void
tampil() const; // menampilkan objek KaryawanKomisiPlusPokok
private:
double
gajiPokok; // gaji pokok
}; // akhir dari kelas
KaryawanKomisiPlusPokok
#endif
|
Gambar 4.11 File
Implementasi KaryawanKomisiPlusPokok: Data private Kelas Basis Tidak Bisa
Diakses dari Kelas Terderivasi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
// Gambar 4.11: KaryawanKomisiPlusPokok.cpp
// Definisi fungsi anggota kelas
KaryawanKomisiPlusPokok.
#include <iostream>
#include "KaryawanKomisiPlusPokok.h" // definisi kelas KaryawanKomisiPlusPokok
using namespace std;
// konstruktor
KaryawanKomisiPlusPokok::KaryawanKomisiPlusPokok(
const
string &pertama, const string &akhir, const string
&ktp,
double
penjualan, double komisi, double gaji )
//
secara eksplisit memanggil konstruktor kelas basis
: KaryawanKomisi( pertama,
akhir, ktp, penjualan, komisi )
{
setGajiPokok( gaji ); // memvalidasi dan menyimpan gaji pokok
} // akhir dari konstruktor
KaryawanKomisiPlusPokok
// menetapkan gaji pokok
void KaryawanKomisiPlusPokok::setGajiPokok( double
gaji )
{
if
( gaji >= 0.0 )
gajiPokok
= gaji;
else
throw
invalid_argument( "Gaji pokok harus >= 0.0" );
} // akhir dari fungsi setGajiPokok
// mengembalikan gaji pokok
double KaryawanKomisiPlusPokok::getGajiPokok() const
{
return
gajiPokok;
} // akhir dari fungsi getGajiPokok
// menghasilkan penghasilan
double KaryawanKomisiPlusPokok::penghasilan() const
{
//
kelas terderivasi tidak bisa mengakses data private pada kelas basis
return gajiPokok + ( besarKomisi *
penjualanKotor );
} // akhir dari fungsi penghasilan
// menampilkan objek KaryawanKomisiPlusPokok
void KaryawanKomisiPlusPokok::tampil() const
{
//
kelas terderivasi tidak bisa mengakses data private pada kelas basis
cout
<< "karyawan komisi bergaji pokok: " <<
namaPertama << ' '
<<
namaAkhir << "\nnomor kartu penduduk: " <<
nomorKTP
<< "\npenjualan kotor: " <<
penjualanKotor
<< "\nbesar komisi: " << besarKomisi
<< "\ngaji pokok: " << gajiPokok;
} // akhir dari fungsi tampil
|
c:\c++\karyawankomisipluspokok.cpp(36) : error C2248:
'besarKomisi' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(37) : see declaration of
'besarKomisi'
c:\c++\karyawankomisipluspokok.cpp(36) : error C2248:
'penjualanKotor' : cannot access private member declared in class
'KaryawanKomisi'
c:\c++\karyawankomisi.h(36) : see declaration of
'penjualanKotor'
c:\c++\karyawankomisipluspokok.cpp(43) : error C2248: 'namaPertama'
: cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(33) : see declaration of
'namaPertama'
c:\c++\karyawankomisipluspokok.cpp(44) : error C2248:
'namaAkhir' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(34) : see declaration of 'namaAkhir'
c:\c++\karyawankomisipluspokok.cpp(45) : error C2248:
'nomorKTP' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(35) : see declaration of 'nomorKTP'
c:\c++\karyawankomisipluspokok.cpp(46) : error C2248:
'penjualanKotor' : cannot access private member declared in class
'KaryawanKomisi'
c:\c++\karyawankomisi.h(36) : see declaration of
'penjualanKotor'
c:\c++\karyawankomisipluspokok.cpp(47) : error C2248:
'besarKomisi' : cannot access private member declared in class 'KaryawanKomisi'
c:\c++\karyawankomisi.h(37) : see declaration of
'besarKomisi'
Gambar 4.11 menunjukkan implementasi
fungsi anggota kelas KaryawanKomisiPlusPokok.
Konstruktor (baris 8-15) mengintroduksi sintaks penginisialisasi kelas basis
(baris 12), yang menggunakan sebuah penginisialisasi anggota untuk melewatkan
argumen kepada konstruktor kelas basis (KaryawanKomisi).
C++ mensyaratkan bahwa konstruktor kelas terderivasi memanggil konstruktor
kelas basis untuk menginisialisasi anggota-anggota data kelas basis yang
diwariskan kepada kelas terderivasi. Baris 12 melakukan hal ini secara
eksplisit dengan memanggil konstruktor KaryawanKomisi
lewat nama, melewatkan parameter-parameter konstruktor pertama, akhir, ktp, penjualan,
dan komisi sebagai argumen untuk
menginisialisasi anggota-anggota data kelas basis namaPertama, namaAkhir, nomorKTP, penjualanKotor, dan besarKomisi.
Jika konstruktor KaryawanKomisiPlusPokok
tidak memanggil konstruktor KaryawanKomisi
secara eksplisit, maka C++ akan mencoba memanggil konstruktor default KaryawanKomisi secara implisit. Karena
kelas KaryawanKomisi tidak memiliki
konstruktor default, maka kompiler akan mengeluarkan pesan error. Ingat bahwa
kompiler menyediakan konstruktor default tanpa parameter bagi sembarang kelas
yang tidak secara eksplisit menyertakan sebuah konstruktor. Tetapi, KaryawanKomisi secara eksplisit
menyertakan sebuah konstruktor, sehingga konstruktor default tidak disediakan.
Error Kompilasi
dari Pengaksesan Anggota Data private Kelas Basis
Kompiler membangkitkan error pada untuk
baris 36 pada baris 7.11 karena anggota data private, besarKomisi dan penjualanKotor, pada kelas KaryawanKomisi, tidak diijinkan diakses
oleh fungsi anggota kelas terderivasi KaryawanKomisiPlusPokok.
Kompiler mengeluarkan error lain pada baris 43-46 karena alasan yang sama. Seperti yang Anda
lihat, C++ secara tegas membatasi pengaksesan anggota data private, sehingga bahkan kelas terderivasi (yang secara intim
berelasi dengan kelas basisnya) tidak dapat mengakses data private kelas basis.
Mencegah Error
di dalam Kelas KaryawanKomisiPlusPokok
Pada Gambar 4.11 disengaja untuk
mencantumkan kode error untuk menekankan bahwa fungsi anggota kelas terderivasi
tidak dapat mengakses data private
kelas basisnya. Error di dalam KaryawanKomisiPlusPokok
dapat dicegah dengan menggunakan fungsi anggota get yang diwarisi dari KaryawanKomisi.
Sebagai contoh, baris 36 seharusnya dapat memanggil getBesarKomisi dan getPenjualanKotor
untuk mengakses anggota-anggota data private kelas KaryawanKomisi seperti besarKomisi
dan penjualanKotor. Hal yang sama,
baris 43-46 seharusnya dapat menggunakan fungsi anggota get yang sesuai untuk mengambil nilai-nilai anggota data kelas
basis. Pada contoh berikutnya, akan ditunjukkan bagaimana menggunakan data protected yang mengijinkan Anda untuk
menghindari masalah yang terjadi pada contoh ini.
Menyertakan
Header Kelas Basis di dalam Header Kelas Terderivasi dengan #include
Perhatikan bahwa header kelas basis
dicantumkan di dalam header kelas terderivasi (baris 8 pada Gambar 4.10). Hal
ini penting karena tiga alasan. Pertama, agar kelas terderivasi bisa
menggunakan nama kelas basis pada baris 11, Anda harus memberitahukan kompiler
bahwa kelas basis eksis (definisi di dalam KaryawnKomisi.h
yang melakukannya). Alasan kedua adalah bahwa kompiler menggunakan definisi
kelas untuk menentukan ukuran sebuah objek dari kelas tersebut. Program klien
yang menciptakan objek suatu kelas harus menyertakan definisi kelas
(menggunakan #include) untuk
memampukan kompiler untuk menyediakan sejumlah memori tertentu untuk objek
tersebut. Ketika menggunakan pewarisan, ukuran objek kelas terderivasi
bergantung dari anggota data yang dideklarasikan secara eksplisit di dalam
definisi kelasnya dan anggota data yang diwarisi secara langsung maupun
tak-langsung dari kelas basisnya.
Penyertaan definisi kelas basis pada
baris 8 memampukan kompiler untuk menentukan memori yang dibutuhkan untuk
anggota data kelas basis yang menjadi bagian dari suatu objek kelas terderivasi
dan oleh karena itu berkontribusi menambah ukuran total objek kelas
terderivasi. Alasan terakhir untuk baris 8 adalah untuk mengijinkan kompiler
dalam menentukan apakah kelas terderivasi menggunakan anggota yang diwarisi
dari kelas basis secara benar. Sebagai contoh, dalam program Gambar 4.10 – 4.11,
kompiler menggunakan header kelas basis untuk menentukan bahwa anggota data
yang sedang diakses oleh kelas terderivasi merupakan anggota data private di dalam kelas basis. Karena
anggota data private tidak bisa
diakses oleh kelas terderivasi, kompiler kemudian membangkitkan error. Kompiler
juga menggunakan prototipe fungsi kelas basis untuk memvalidasi pemanggilan
fungsi yang dilakukan oleh kelas terderivasi terhadap fungsi yang diwarisi dari
kelas basis.
4.4.4 Hirarki Pewarisan KaryawanKomisi-KaryawanKomisiPlusPokok Menggunakan Data protected
Agar kelas KaryawanKomisiPlusPokok dapat secara langsung mengakses anggota
data kelas KaryawanKomisi (namaPertama, namaAkhir, nomorKTP, penjualanKotor, dan besarKomisi), Anda perlu mendeklarasikan semua anggota tersebut
sebagai protected di dalam kelas basis.
Seperti yang telah dijelaskan sebelumnya, anggota protected suatu kelas basis dapat diakses oleh fungsi anggota dan
fungsi friend kelas basis dan oleh
fungsi anggota dan fungsi friend dari
sembarang kelas yang diderivasi dari kelas basis tersebut.
Mendefinisikan
Kelas KaryawanKomisi dengan Data protected
Kelas KaryawanKomisi (Gambar 4.12) sekarang mendeklarasikan
anggota-anggota data namaPertama, namaAkhir, nomorKTP, penjualanKotor,
dan besarKomisi sebagai protected (baris 32-37) sebagai
pengganti private. Implementasi
fungsi anggota identik dengan yang ada pada Gambar 4.5, jadi KaryawanKomisi.cpp tidak ditampilkan di
sini.
Gambar 4.12 Definisi Kelas KaryawanKomisi dengan
Data protected
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// Gambar 4.12: KaryawanKomisi.h
// Definisi kelas KaryawanKomisi dengan data
protected.
#ifndef KOMISI_H
#define KOMISI_H
#include <string> // Kelas string standard C++
using namespace std;
class KaryawanKomisi
{
public:
KaryawanKomisi(
const string &, const string &, const string
&,
double
= 0.0, double = 0.0 );
void setNamaPertama( const
string & ); // menetapkan nama pertama
string getNamaPertama() const; //
mengembalikan nama pertama
void setNamaAkhir( const
string & ); // menetapkan nama akhir
string getNamaAkhir() const; //
mengembalikan nama akhir
void setNomorKTP( const string
& ); // menetapkan nomor KTP
string getNomorKTP() const; //
mengembalikan nomor KTP
void setPenjualanKotor( double
); // menetapkan jumlah penjualan kotor
double getPenjualanKotor() const;
// mengembalikan jumlah penjualan kotor
void setBesarKomisi( double ); //
menetapkan besar komisi (persentase)
double getBesarKomisi() const;
// mengembalikan besar komisi
double penghasilan() const; //
menghitung penghasilan
void tampil() const; //
menampilkan objek KaryawanKomisi
protected:
string
namaPertama;
string
namaAkhir;
string
nomorKTP;
double
penjualanKotor; // penjualan kotor mingguan
double
besarKomisi; // persentasi komisi
}; // akhir dari kelas KaryawanKomisi
#endif
|
Kelas
KaryawanKomisiPlus
Definisi kelas KaryawanKomisiPlusPokok dari Gambar 4.10 – 4.11 tetap tidak
berubah, jadi tidak akan ditampilkan kembali di sini. Karena KaryawanKomisiPlusPokok mewarisi kelas KaryawanKomisi terperbarui pada Gambar 4.12,
objek-objek KaryawanKomisiPlusPokok
dapat mengakses anggota data terwarisi yang dideklarasikan protected di dalam kelas KaryawanKomisi
(yaitu namaPertama, namaAkhir, nomorKTP, penjualanKotor,
dan besarKomisi). Hasilnya, kompiler
tidak membangkitkan error ketika mengompilasi fungsi anggota penghasilan dan tampil pada kelas KaryawanKomisiPlusPokok
pada Gambar 4.11 (baris 33-37 dan 40-48). Ini menunjukkan hak spesial yang dimiliki kelas terderivasi
dalam mengakses anggota data protected
milik kelas basis. Objek suatu kelas terderivasi juga dapat mengakses anggota protected di dalam sembarang kelas basis
tak-langsung yang mewari kelas terderivasi tersebut.
Kelas KaryawanKomisiPlusPokok tidak mewarisi konstruktor KaryawanKomisi. Namun, konstruktor kelas
KaryawanKomisiPlusPokok (Gambar 4.11,
baris 8-15) memanggil konstruktor kelas KaryawanKomisi
secara eksplisit menggunakan sintaks penginisialisasi anggota (baris 12). Ingat
bahwa konstruktor KaryawanKomisiPlusPokok
harus secara eksplisit memanggil konstruktor kelas KaryawanKomisi, karena kelas KaryawanKomisi
tidak memuat konstruktor default yang dapat dipanggil secara implisit.
Menguji Kelas
Kelas KaryawanKomisiPlus Termodifikasi
Untuk menguji hirarki kelas
terperbarui, program pada Gambar 4.9 akan digunakan kembali. Seperti tertampil
pada Gambar 4.13, keluarannya identik dengan yang ada pada Gambar 7.9. Anda
telah menciptakan KaryawanKomisiPlusPokok
tanpa menggunakan pewarisan dan juga menciptakan KaryawanKomisiPlusPokok menggunakan pewarisan; tetapi, kedua versi
kelas tersebut memiliki fungsionalitas yang sama. Kode untuk kelas KaryawanKomisiPlusPokok (header dan file
implementasi), sebanyak 74 baris, jauh lebih pendek dari pada kode untuk versi
non-pewarisan, sebanyak 161 baris, karena versi pewarisan menyerap fungsionalitasnya
dari KaryawanKomisi, sedangkan versi
non-pewarisan tidak menyerap fungsionalitasnya dari manapun. Di samping itu,
sekarang hanya terdapat satu salinan dari fungsionalitas KaryawanKomisi yang dideklarasikan dan didefinisikan di dalam kelas
KaryawanKomisi. Hal ini membuat kode
sumber menjadi lebih mudah dirawat, dimodifikasi dan dikembangkan.
Gambar 4.13 Data protected Kelas Basis dapat Diakses dari Kelas
Terderivasi
Informasi karyawan didapatkan dengan fungsi-fungsi get:
Nama pertama adalah Rotua
Nama akhir adalah Marolop
Nomor kartu penduduk adalah 333-33-3333
Penjualan kotor adalah 5000.00
Besar komisi adalah 0.04
Gaji pokok adalah 300.00
Informasi karyawan terperbarui ditampilkan oleh fungsi
tampil:
karyawan komisi bergaji pokok: Rotua Marolop
nomor kartu penduduk: 333-33-3333
penjualan kotor: 5000.00
besar komisi: 0.04
gaji pokok: 1000.00
Penghasilan karyawan: Rp. 1200.00
4.4.5 Hirarki Pewarisan KaryawanKomisi-KaryawanKomisiPlusPokok Menggunakan Data private
Sekarang akan diuji kembali hirarki kelas
yang ada sekali lagi, kali ini menggunakan praktek pemrograman yang benar.
Kelas KaryawanKomisi sekarang
mendeklarasikan anggota data namaPertama,
namaAkhir, nomorKTP, penjualanKotor,
dan besarKomisi sebagai private seperti yang sebelumnya
ditampilkan pada baris 32-37 pada Gambar 4.4.
Perubahan pada
Definisi Fungsi Kelas KaryawanKomisi
Di dalam implementasi konstruktor KaryawanKomisi (Gambar 4.14, baris
8-15), Anda menggunakan penginisialisasi anggota (baris 11) untuk menetapkan
nilai anggota data namaPertama, namaAkhir, dan nomorKTP. Sekarang akan ditunjukkan bagaimana kelas terderivasi KaryawanKomisiPlusPokok (Gambar 4.15)
agar dapat memanggil fungsi-fungsi anggota non-private kelas basis (setNamaPertama,
getNamaPertama, setNamaAkhir, getNamaAkhir,
setNomorKTP, dan getNomorKTP) untuk memanipulasi anggota-anggota data tersebut.
Di dalam tubuh konstruktor dan di dalam
tubuh fungsi anggota penghasilan
(baris 84-87) dan fungsi anggota tampil
(baris 90-97), Anda memanggil beberapa fungsi set dan get untuk
mengakses anggota data private. Jika
Anda memutuskan untuk mengubah nama anggota data, definisi penghasilan dan tampil
tidak perlu dimodifikasi, hanya definisi beberapa metode get dan set, yang secara
langsung memanipulasi anggota data, yang perlu diubah. Perubahan ini hanya
terjadi di dalam kelas basis dan tidak ada perubahan yang perlu dilakukan pada
kelas terderivasi. Melakukan lokalisasi perubahan seperti ini merupakan praktek
perekayasaaan perangkat lunak yang baik.
Gambar 4.14 Definisi Kelas KaryawanKomisi
Menggunakan Fungsi Anggota untuk Memanipulasi Data private
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
// Gambar 4.14: KaryawanKomisi.cpp
// Definisi fungsi anggota kelas
KaryawanKomisi.
#include <iostream>
#include "KaryawanKomisi.h" // definisi
kelas KaryawanKomisi
using namespace std;
// konstruktor
KaryawanKomisi::KaryawanKomisi(
const string
&pertama, const string &akhir, const string &ktp,
double penjualan, double
komisi )
: namaPertama( pertama ),
namaAkhir( akhir ), nomorKTP( ktp )
{
setPenjualanKotor(
penjualan ); // memvalidasi dan menyimpan penjualan kotor
setBesarKomisi(
komisi ); // memvalidasi dan menyimpan besar komisi
} // akhir dari konstruktor KaryawanKomisi
// menetapkan nama pertama
void KaryawanKomisi::setNamaPertama( const
string &pertama )
{
namaPertama = pertama; // seharusnya
divalidasi
} // akhir dari fungsi setNamaPertama
// mengembalikan nama pertama
string KaryawanKomisi::getNamaPertama() const
{
return namaPertama;
} // akhir dari fungsi getNamaPertama
// menetapkan nama akhir
void KaryawanKomisi::setNamaAkhir( const string
&akhir )
{
namaAkhir = akhir; // seharusnya divalidasi
} // akhir dari fungsi setNamaAkhir
// mengembalikan nama akhir
string KaryawanKomisi::getNamaAkhir() const
{
return namaAkhir;
} // akhir dari fungsi getNamaAkhir
// menetapkan nomor kartu penduduk
void KaryawanKomisi::setNomorKTP( const string
&ktp )
{
nomorKTP = ktp; // seharusnya divalidasi
} // akhir dari fungsi setNomorKTP
// mengembalikan nomor kartu penduduk
string KaryawanKomisi::getNomorKTP() const
{
return nomorKTP;
} // akhir dari fungsi getNomorKTP
// menetapkan jumlah penjualan kotor
void KaryawanKomisi::setPenjualanKotor( double
penjualan )
{
if ( penjualan >= 0.0 )
penjualanKotor = penjualan;
else
throw invalid_argument( "penjualan
kotor harus >= 0.0" );
} // akhir dari fungsi setPenjualanKotor
// menghasilkan jumlah penjualan kotor
double KaryawanKomisi::getPenjualanKotor() const
{
return penjualanKotor;
} // akhir dari fungsi penjualanKotor
// menetapkan besar komisi
void KaryawanKomisi::setBesarKomisi( double
komisi )
{
if ( komisi > 0.0 &&
komisi < 1.0 )
besarKomisi = komisi;
else
throw invalid_argument( "besar
komisi harus di antara > 0.0 dan < 1.0" );
} //
akhir dari fungsi setBesarKomisi
// mengembalikan besar komisi
double KaryawanKomisi::getBesarKomisi() const
{
return besarKomisi;
} // akhir dari fungsi getBesarKomisi
// menghitung penghasilan
double KaryawanKomisi::penghasilan() const
{
return
getBesarKomisi()
* getPenjualanKotor();
} // akhir dari fungsi penghasilan
// menampilkan objek KaryawanKomisi
void KaryawanKomisi::tampil() const
{
cout
<< "karyawan komisi: "
<<
getNamaPertama()
<< ' ' << getNamaAkhir()
<<
"\nnomor kartu penduduk: " << getNomorKTP()
<<
"\npenjualan kotor: " << getPenjualanKotor()
<<
"\nbesar komisi: " << getBesarKomisi();
} // akhir dari fungsi tampil
|
Perubahan pada
Definisi Fungsi Kelas KaryawanKomisiPlusPokok
Kelas KaryawanKomisiPlusPokok mewarisi fungsi-fungsi anggota public kelas KaryawanKomisi dan dapat mengakses anggota data private melalui fungsi anggota yang
diwarisi. Header KaryawanKomisiPlusPokok
tetap tidak berubah dari Gambar 4.10. Kelas ini mengalami perubahan pada
implementasi fungsi anggota (Gambar 4.15) yang membedakannya dari versi
sebelumnya (Gambar 4.10 - 4.11). Fungsi anggota penghasilan (Gambar 4.15, baris 33-36) dan tampil (baris 39-47) masing-masing memanggil fungsi anggota getGajiPokok untuk mendapatkan nilai
gaji pokok, menggantikan pengaksesan gajiPokok
secara langsung. Hal ini mengisolasi penghasilan dan tampil dari perubahan yang
berpotensi terjadi pada anggota data gajiPokok
pada implementasi. Sebagai contoh, jika Anda memutuskan untuk menamai-ulang
anggota data gajiPokok atau mengubah
tipenya, maka hanya fungsi anggota getGajiPokok
dan setGajiPokok yang perlu untuk
diubah.
Gambar 4.15 Kelas KaryawanKomisiPlusPokok yang Mewarisi
Kelas KaryawanKomisi tetapi tidak bisa secara langsung mengakses data private
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
// Gambar 4.15: KaryawanKomisiPlusPokok.cpp
// Definisi fungsi anggota kelas
KaryawanKomisiPlusPokok.
#include <iostream>
#include "KaryawanKomisiPlusPokok.h" // definisi kelas KaryawanKomisiPlusPokok
using namespace std;
// konstruktor
KaryawanKomisiPlusPokok::KaryawanKomisiPlusPokok(
const
string &pertama, const string &akhir, const string
&ktp,
double
penjualan, double komisi, double gaji )
//
secara eksplisit memanggil konstruktor kelas basis
:
KaryawanKomisi( pertama, akhir, ktp, penjualan, komisi )
{
setGajiPokok( gaji ); // memvalidasi dan menyimpan gaji pokok
} // akhir dari konstruktor
KaryawanKomisiPlusPokok
// menetapkan gaji pokok
void KaryawanKomisiPlusPokok::setGajiPokok( double
gaji )
{
if
( gaji >= 0.0 )
gajiPokok
= gaji;
else
throw
invalid_argument( "Gaji pokok harus >= 0.0" );
} // akhir dari fungsi setGajiPokok
// mengembalikan gaji pokok
double KaryawanKomisiPlusPokok::getGajiPokok() const
{
return
gajiPokok;
} // akhir dari fungsi getGajiPokok
// menghasilkan penghasilan
double KaryawanKomisiPlusPokok::penghasilan() const
{
return
KaryawanKomisi::penghasilan();
} // akhir dari fungsi penghasilan
// menampilkan objek KaryawanKomisiPlusPokok
void KaryawanKomisiPlusPokok::tampil() const
{
cout
<< "karyawan komisi bergaji pokok: ";
//
memanggil fungsi tampil kelas KaryawanKomisi
KaryawanKomisi::tampil();
cout
<< "\ngaji pokok: " << getGajiPokok();
} // akhir dari fungsi tampil
|
Fungsi Anggota
penghasilan Kelas KaryawanKomisiPlusPokok
Fungsi penghasilan pada kelas KaryawanKomisiPlusPokok
(Gambar 4.15, baris 33-36) mendefinisikan-ulang fungsi penghasilan kelas KaryawanKomisi
(Gambar 4.14, baris 84-87) untuk menghitung penghasilan dari karyawan komisi
bergaji pokok. Versi penghasilan pada
kelas KaryawanKomisiPlusPokok
mendapatkan bagian penghasilan karyawan yang hanya berbasis komisi saja dengan
memanggil fungsi penghasilan pada
kelas KaryawanKomisi dengan ekspresi KaryawanKomisi::penghasilan() (Gambar 4.15,
baris 35). Fungsi penghasilan pada
kelas KaryawanKomisiPlusPokok
kemudian menambahkan gaji pokok kepada nilai tersebut untuk menghitung total
penghasilan karyawan. Perhatikan sintaks yang digunakan untuk memanggil fungsi
anggota terdefinisi-ulang pada kelas basis dari kelas terderivasi; yaitu dengan
menempatkan nama kelas basis dan operator resolusi skop (::) sebelum nama
fungsi anggota kelas basis. Dengan memiliki fungsi penghasilan pada kelas KaryawanKomisiPlusPokok
untuk memanggil fungsi anggota penghasilan
pada kelas KaryawanKomisi dalam
menghitung sebagian dari penghasilan objek KaryawanKomisiPlusPokok,
Anda telah terhindar dari praktek penduplikasian kode dan berhasil mereduksi masalah
perawatan-kode.
Fungsi Anggota
tampil Kelas KaryawanKomisiPlusPokok
Sama halnya, fungsi tampil pada kelas KaryawanKomisiPlusPokok (Gambar 4.15,
baris 39-47) mendefinisikan-ulang fungsi tampil
pada kelas KaryawanKomisi (Gambar 4.14,
baris 90 - 97) untuk menampilkan informasi karyawan komisi bergaji pokok. Versi
baru ini menampilkan sebagian dari informasi objek KaryawanKomisiPlusPokok dengan memanggil fungsi anggota tampil pada kelas KaryawanKomisi dengan ekspresi KaryawanKomisi::tampil()
(Gambar 4.15, baris 44). Fungsi tampil
pada kelas KaryawanKomisiPlusPokok
kemudian menampilkan sisa informasi objek KaryawanKomisiPlusPokok
yang lain.
Kesimpulan
Ketika menciptakan sebuah kelas, daripada menulis anggota data dan anggota
fungsi yang baru, Anda bisa menciptakan kelas baru yang mewarisi
anggota-anggota dari kelas yang sudah ada. Kelas yang sudah ada ini disebut
dengan kelas basis, dan kelas baru yang mewarisi tersebut dikenal dengan kelas
terderivasi. Bahasa pemrograman lain seperti Java dan C# menyebutkan kelas
basis sebagai superkelas dan kelas terderivasi sebagai subkelas. Kelas
terderivasi merepresentasikan grup-grup objek yang lebih spesifik.
Karena setiap objek kelas terderivasi merupakan objek kelas basisnya, dan
satu kelas basis dapat memiliki banyak kelas terderivasi, maka himpunan objek
yang direpresentasikan oleh kelas basis umumnya lebih besar atau lebih umum
dari himpunan objek yang direpresentasikan oleh sembarang kelas terderivasinya.
Anggota public suatu kelas basis
dapat diakses dari dalam tubuh kelas tersebut dan dari tempat manapun yang
dapat dilakukan program (misalnya lewat nama, referensi, atau pointer) di dalam
kelas basis tersebut atau dari salah satu kelas terderivasinya.Anggota private suatu kelas basis dapat diakses
dari dalam tubuh kelas tersebut dan oleh friend
dari kelas basis tersebut. Pada bagian ini, akan dikenalkan penspesifikasi
akses protected. Penggunaan akses protected menawarkan level proteksi
menengah antara akses public dan private. Anggota protected suatu kelas basis dapat diakses dari dalam tubuh kelas
basis tersebut, oleh anggota dan friend
dari kelas basis tersebut, dan oleh anggota dan friend dari sembarang kelas yang diderivasi dari kelas basis
tersebut.
Latihan
1)
Banyak program yang ditulis
dengan pewarisan dapat ditulis dengan kompsosisi, dan sebaliknya.
Tulis-ulanglah kelas KaryawanKomisiPlusPokok
pada hirarkri KaryawanKomisi-KaryawanKomisiPlusPokok menggunakan
komposisi menggantikan pewarisan. Setelah Anda melakukannya, nilailah aspek
kecocokan atas dua pendekatan (pewarisan dan komposisi) tersebut. Pendekatan
manakah yang lebih bagus? Mengapa?
2)
Gambarlah hirarki pewarisan
untuk mahasiswa di suatu universitas yang sama dengan hirarki pada Gambar 4.2.
Gunakan Mahasiswa sebagai kelas basis
hirarki, kemudian cantumkan kelas MahasiswaSarjana
dan kelas MahasiswaPascaSarjana yang
mewarisi dari Mahasiswa. Lanjutkan untuk
memperluas hirarki sedalam dan sebanyak mungkin level yang Anda bisa. Sebagai
contoh, Yunior dan Senior dapat mewarisi kelas MahasiswaSarjana, dan MahasiswaMaster dan MahasiswaDoktor dapat mewarisi kelas MahasiswaPascaSarjana. Setelah menggambar hirarki, diskusikan
relasi yang eksis di antara kelas. Selanjutnya, realisasikan hirarki pewarisan
tersebut dengan kode C++.
3)
Tulislah sebanyak mungkin jenis
bangun yang bisa Anda pikirkan baik bangun dua dimensi maupun bangun tiga
dimensi. Formasikan semuanya ke dalam hirarki Bangun menjadi sebanyak mungkin level yang Anda bisa. Hirarki Anda
harus memiliki kelas bangun Bangun yang mewarisi kelas BangunDuaDimensi dan BangunTigaDimensi.
Setelah menggambar hirarki, diskusikan relasi yang eksis di antara kelas.
Selanjutnya, realisasikan hirarki pewarisan tersebut dengan kode C++.
No comments:
Post a Comment