8.
Pemrograman Berorientasi Objek: Pewarisan
Pengantar
Ketika menciptakan sebuah kelas,
daripada harus menuliskan metode dan variabel instans yang baru, programer
dapat mewarisi variabel, properti, dan metode dari kelas lain. Kelas yang
diwarisi disebut dengan kelas basis, dan kelas yang mewarisi dikenal dengan
kelas terderivasi. (Pada bahasa pemrograman yang lain, seperti Java, kelas
basis disebut dengan superkelas dan kelas terderivasi dikenal dengan subkelas).
Setelah diciptakan, setiap kelas terderivasi bisa menjadi kelas basis bagi
kelas terderivasi berikutnya. Kelas terderivasi, yang memiliki variabel,
properti, dan metode yang unik biasanya lebih besar dari kelas basisnya. Oleh
karena itu, kelas terderivasi lebih spesifik daripada kelas basisnya dan
merepresentasikan grup objek yang lebih detil. Secara umum, kelas terderivasi
memiliki watak dari kelas basisnya dan watak tambahan. Kelas basis langsung
adalah kelas basis yang diwarisi kelas terderivasi secara eksplisit. Kelas
basis tak-langsung adalah kelas basis yang diwarisi dari dua atau lebih level
di dalam hirarki pewarisan oleh suatu kelas terderivasi. Pewarisan tunggal
adalah kasus dimana sebuah kelas terderivasi hanya mewarisi dari sebuah kelas
basis. Visual Basic tidak mendukung keberadaan pewarisan jamak (dimana sebuah
kelas terderivasi mewarisi lebih dari satu kelas basis).
Setiap objek dari sebuah kelas
terderivasi juga merupakan objek dari kelas basis yang mewarisi kelas
terderivasi tersebut. Namun, objek kelas basis bukanlah objek dari kelas
terderivasinya. Sebagai contoh, semua mobil adalah kendaraan, tetapi tidak
semua kendaraan adalah mobil.
Anda perlu membedakan antara relasi
“adalah suatu” dengan relasi “memiliki suatu”. Relasi “adalah suatu”
merepresentasikan pewarisan. Di dalam relasi “adalah suatu”, setiap objek kelas
terderivasi diperlakukan sebagai objek kelas basisnya. Sebagai contoh, mobil adalah suatu kendaraan. Sebaliknya,
relasi “memiliki suatu” merepresentasikan komposisi (yang telah didiskusikan
pada Bab 7). Dalam relasi “memiliki suatu”, setiap objek kelas memuat satu atau
lebih referensi objek sebagai anggota. Sebagai contoh, mobil memiliki suatu stir.
Metode kelas terderivasi memerlukan
akses terhadap metode, properti, dan variabel instans kelas basisnya. Metode
kelas terderivasi dapat mengakses anggota tak-Private kelas basisnya. Anggota kelas basis yang tidak bisa diakses
oleh properti atau metode kelas terderivasinya melalui pewarisan dideklarasikan
Private di dalam kelas basis. Kelas
terderivasi dapat mengakses anggota kelas basis Private, tetapi hanya melalui metode dan properti tak-Private yang disediakan di dalam kelas
basis dan diwarisi oleh kelas basis.
Satu masalah pada pewarisan adalah
bahwa kelas terderivasi dapat mewarisi properti dan metode yang tidak
dibutuhkannya. Hal ini merupakan tanggung jawab programer untuk memastikan
bahwa kapabilitas yang disediakan suatu kelas cocok untuk kelas terderivasinya.
Bahkan bila suatu properti atau metode kelas basis cocok untuk kelas
terderivasinya, kelas terderivasi tersebut seringkali memerlukan properti atau
metode yang dapat melakukan tugasnya dengan cara yang spesifik (sedikit
berbeda). Pada kasus semacam itu, properti atau metode kelas basis dapat
didefinisikan-ulang (overridden) di
dalam kelas terderivasi dengan implementasi yang sesuai.
Kelas
Basis dan Kelas Terderivasi
Gambar 8.1 mencantumkan beberapa contoh
kelas basis dan kelas terderivasinya.
Kelas Basis
|
Kelas Terderivasi
|
CMahasiswa
CBangun
CPinjaman
CKaryawan
CAkun
|
CMahasiswaPascasarjana
CMahasiswaSarjana
CLingkaran
CPersegipanjang
CSegitiga
CPinjamanMobil
CPinjamanKPR
CRenovasiRumah
CPejabat
CPegawai
CAkunSimpanan
CAkunDeposito
|
Gambar 8.1 Beberapa contoh
pewarisan
Setiap objek kelas terderivasi “adalah
suatu” objek kelas basisnya, dan sebuah kelas basis dapat memiliki lebih dari
satu kelas terderivasi; oleh karena itu, himpunan objek yang direpresentasikan
sebuah kelas basis umumnya lebih luas daripada himpunan objek yang
direpresentasikan oleh salah satu dari kelas terderivasinya. Sebagai contoh,
kelas basis CKendaraan mewakili
semua kendaraan, termasuk mobil, truk, kapal, sepeda, dan lainnya. Sebaliknya,
kelas terderivasi CMobil hanya
mewakili himpunan kecil dari semua CKendaraan.
Relasi pewarisan membentuk struktur
hirarki pohon. Akan disajikan sebuah hirarki pewarisan sederhana. Komunitas
universitas memiliki ribuan anggota. Anggota tersebut dapat mewakili karyawan,
mahasiswa, dan alumni. Karyawan bisa berasal dari dosen dan pegawai
administrasi. Anggota dosen bisa menjadi pejabat (seperti dekan dan ketua
jurusan) atau sebagai pengajar biasa. Struktur organisasional ini menghasilkan
hirarki pewarisan, seperti ditampilkan pada Gambar 8.2. Perhatikan bahwa
hirarki pewarisan dapat memuat banyak kelas lain. Sebagai contoh, mahasiswa
dapat berasal dari mahasiswa sarjana atau mahasiswa pascasarjana. Setiap anak
panah di dalam hirarki merepresentasikan relasi “adalah suatu”. Sebagai contoh,
dengan mengikuti anak panah pada hirarki kelas ini, dapat dinyatakan bahwa “CKaryawan adalah suatu CAnggotaKomunitas” atau “CPengajar adalah suatu CDosen”. CAnggotaKomunitas
adalah kelas basis langsung bagi CKaryawan,
CMahasiswa, dan CAlumni. Di samping itu, CAnggotaKomunitas
adalah kelas basis tak langsung bagi semua kelas lain (bagi CDosen, CStaff, CPejabat, dan CPengajar) di dalam diagram hirarki.
Gambar 8.2 Hirarki
pewarisan untuk CAnggotaKomunitas
universitas
Dimulai dari bawah diagram, pembaca
dapat mengikuti anak panah dan menerapkan relasi “adalah suatu” ke kelas basis
teratas. Sebagai contoh, CPejabat adalah suatu anggota CDosen, adalah suatu CKaryawan
dan adalah suatu CAnggotaKomunitas. Dalam Visual Basic, CPejabat juga merupakan sebuah Object,
karena semua kelas dalam Visual Basic memiliki Object sebagai kelas basis langsung atau kelas basis tak-langsung.
Jadi, semua kelas dalam Visual Basic tekoneksi melalui relasi pewarisan dan
mewarisi delapan metode yang didefinisikan oleh kelas Object.
Hirarki pewarisan lain adalah hirarki CBangun pada Gambar 8.3. Untuk
menspesifikasi bahwa kelas CBangunDuaDimensi
diderivasi dari (mewarisi dari) kelas CBangun,
kelas CBangunDuaDimensi perlu didefinisikan
dalam Visual Basic sebagai berikut:
Class CBangunDuaDimensi
Inherits CBangun
Pada Bab 8, telah dijelaskan secara
singkat tentang relasi memiliki-suatu, dimana kelas dapat memiliki anggota
berupa referensi yang menunjuk ke objek dari kelas lain. Relasi semacam itu
menciptakan kelas dengan melakukan komposisi terhadap kelas yang sudah ada.
Sebagai contoh, jika diberikan kelas CKaryawan,
CTanggalLahir, dan CNomorTelepon, maka sangat tidak tepat
untuk mengatakan bahwa CKaryawan adalah suatu CTanggalLahir atau bahwa CKaryawan
adalah suatu CNomorTelepon. Namun, adalah hal yang tepat untuk mengatakan bahwa CKaryawan memiliki suatu CTanggalLahir
dan bahwa CKaryawan memiliki suatu CNomorTelepon.
Dengan pewarisan, anggota Private suatu kelas basis tidak dapat
diakses secara langsung dari kelas terderivasinya, tetapi anggota Private tersebut tetap diwariskan
kepada kelas terderivasinya. Semua anggota kelas basis yang lain (kecuali Private) mendapatkan hak ases yang sama
ketika menjadi anggota dari kelas terderivasi (yaitu, anggota Public pada kelas basis menjadi anggota
Public pada kelas terderivasi dan
anggota Protected pada kelas basis
menjadi anggota Protected pada kelas
terderivasi). Melalui anggota kelas basis yang diwarisi, kelas terderivasi
dapat memanipulasi anggota Private
kelas basis (jika anggota yang diwarisi ini menyediakan fungsionalitas semacam
itu di dalam kelas basis).
Gambar 8.3 Hirarki
pewarisan kelas CBangun
Anggota
Protected dan Friend
Bab 7 telah didiskusikan pemodifikasi
akses anggota Public dan Private. Anggota Public kelas basis dapat diakses dari mana saja sepanjang program
memiliki sebuah referensi yang menunjuk ke objek kelas basis tersebut atau ke
objek salah satu kelas terderivasinya. Anggota Private kelas basis hanya dapat diakses di dalam tubuh kelas basis
tersebut. Pada bagian ini, akan dikenalkan dua pemodifikasi akses yang lain, Protected dan Friend.
Pemodifikasi akses Protected menawarkan proteksi dengan level di antara akses Public dan Private. Anggota Protected
kelas basis hanya dapat diakses di dalam kelas basis tersebut atau di dalam
sembarang kelas yang diderivasi dari kelas basis itu.
Level akses menengah yang lain dikenal
dengan akses Friend. Anggota Friend kelas basis hanya dapat diakses
oleh objek yang dideklarasikan di dalam assembly yang sama. Perhatikan bahwa
sebuah anggota Friend dapat diakses
dari bagian manapun pada assembly, yang di dalamnya anggota Friend dideklarasikan, bukan hanya dari
dalam kelas yang diderivasi dari kelas basis terkait.
Metode kelas terderivasi dapat menunjuk
ke anggota Public, Protected, dan Friend pada kelas basis hanya dengan menggunakan nama anggota.
Ketika metode kelas terderivasi mendefinisikan-ulang anggota kelas basis,
anggota kelas basis tersebut dapat diakses dari kelas terderivasi dengan
membubuhkan nama anggota kelas basis dengan katakunci MyBase, diikuti dengan operator dot.
Relasi
antara Kelas Basis dan Kelas Terderivasi
Pada bagian ini, akan digunakan hirarki
titik-lingkaran untuk mendiskusikan relasi antara kelas basis dan kelas
terderivasi. Relasi titik-lingkaran tampak sedikit “aneh” ketika didiskusikan
dalam konteks bahwa sebuah lingkaran “adalah suatu” titik; namun, contoh ini
akan mendiskusikan pewarisan struktural, yang berfokus pada bagaimana kelas
basis dan kelas terderivasi berelasi satu sama lain. Pada Bab 9, akan disajikan
contoh pewarisan yang lebih “alami”.
Diskusi tentang relasi titik-lingkaran
akan dibagi menjadi beberapa bagian. Pertama, akan diciptakan kelas CTitik, yang secara langsung mewarisi
kelas System.Object dan memuat
sepasang koordinat x-y sebagai data Private. Kemudian, akan diciptakan kelas CLingkaran, yang juga mewarisi secara langsung kelas System.Object dan memuat sepasang
koordinat x-y sebagai data Private
(merepresentasikan lokasi pusat lingkaran) dan sebuah radius. Anda tidak
menggunakan pewarisan untuk menciptakan kelas CLingkaran. Selanjutnya, diciptakan kelas CLingkaran2, yang secara langsung mewarisi kelas CTitik (yaitu, kelas Lingkaran2 “adalah suatu” CTitik tetapi juga memuat sebuah
radius) dan mencoba menggunakan anggota Private
pada CTitik, yang menghasilkan error
kompilasi, karena kelas terderivasi tidak memiliki hak akses terhadap data Private kelas basis. Kemudian
ditunjukkan bagaimana mendeklarasikan data CTitik
sebagai Protected, bagaimana
menciptakan kelas CLingkaran3 yang
juga mewarisi kelas CTitik yang
dapat mengakses data tersebut. Setelah penggunaan data Protected didiskusikan, data CTitik
ditetapkan kembali menjadi Private,
kemudian akan ditunjukkan bagaimana kelas CLingkaran4
(yang juga mewarisi kelas CTitik)
dapat menggunakan metode CTitik
untuk memanipulasi data Private pada
CTitik.
Pertama-tama akan diperiksa definisi
kelas CTitik (kode 8.1). Layanan Public pada kelas CTitik memuat dua konstruktor (baris 11-25), properti X dan Y (baris 28-51) dan metode ToString
(baris 54-56). Variabel instans mX
dan mY dari CTitik dispesifikasi sebagai Private
(baris 8), sehingga objek dari kelas lain tidak dapat mengakses mX dan mY secara langsung.
Telah disebutkan sebelumnya bahwa
konstruktor kelas tidak diwariskan. Oleh karena itu, kelas CTitik tidak mewarisi konstruktor kelas Object. Namun, konstruktor kelas CTitik (baris 11-25) memanggil konstruktor kelas Object secara implisit. Kenyataannya,
tugas pertama yang dilakukan oleh sembarang konstruktor kelas terderivasi adalah
memanggil konstruktor kelas basis langsungnya, secara implisit atau eksplisit.
Jika kode tidak memuat pemanggilan eksplisit terhadap konstruktor kelas basis,
maka pemanggilan implisit dilakukan terhadap konstruktor default (tanpa
argumen) kelas basis. Komentar pada baris 13 dan 22 mengindikasikan lokasi
dimana pemanggilan terhadap konstruktor default kelas basis Object terjadi.
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
|
' Kode 8.1: Titik.vb
' kelas CTitik
merepresentasikan pasangan koordinat x-y.
Public Class
CTitik
' secara implisit mewarisi Object
' koordinat titik
Private
mX, mY As Integer
' konstruktor default
Public
Sub New()
' pemanggilan implisit terhadap
konstruktor Object terjadi di sini
X = 0
Y = 0
End
Sub ' New
' konstruktor
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer)
' pemanggilan implisit terhadap
konstruktor Object terjadi di sini
X = xNilai
Y = yNilai
End
Sub ' New
' properti X
Public
Property X() As Integer
Get
Return mX
End
Get
Set(ByVal
xNilai As Integer)
mX = xNilai ' tidak perlu
validasi
End
Set
End
Property ' X
' properti Y
Public
Property Y() As Integer
Get
Return mY
End
Get
Set(ByVal yNilai As Integer)
mY = yNilai ' tidak perlu
validasi
End
Set
End
Property ' Y
' menghasilkan representasi String atas
CTitik
Public
Overrides Function ToString() As
String
Return "[" & mX &
", " & mY & "]"
End
Function ' ToString
End Class '
CTitik
|
Perhatikan bahwa metode ToString (baris 54-56) memuat katakunci
Overrides di dalam deklarasinya.
Setiap kelas dalam Visual Basic (seperti kelas CTitik) mewarisi secara langsung atau tak-langsung kelas System.Object, yang merupakan akar dari
semua hirarki pewarisan. Seperti dinyatakan sebelumnya, ini berarti bahwa
setiap kelas mewarisi delapan metode yang didefinisikan oleh kelas Object. Salah satu metode tersebut
adalah ToString, yang menghasilkan
nilai balik berupa sebuah representasi String.
Metode ToString dari kelas CTitik mendefinisikan-ulang ToString asli dari kelas Object. Ketika dipanggil, metode ToString dari kelas CTitik menghasilkan nilai balik berupa
sebuah String yang memuat pasangan nilai mX
dan mY (baris 55).
Dalam Visual Basic, metode kelas basis
harus dideklarasikan Overridable
jika metode itu akan didefinisikan-ulang di dalam kelas terderivasi. Metode ToString dari kelas Object dideklarasikan Overridable, yang memampukan kelas CTitik untuk mendefinisikan-ulang
metode ini. Untuk melihat header metode ToString,
Anda bisa memilih Help > Index...,
dan mengetikkan Object.ToString di
dalam kotak teks pencarian. Halaman yang ditampilkan memuat deskripsi atas
metode ToString, yang mencakut
header berikut:
Overridable Public Function ToString() As String
Katakunci Overridable membolehkan programer untuk mendefinisikan-ulang metode
tersebut di dalam kelas terderivasi. Metode yang tidak dideklarasikan Overridable tidak dapat
didefinisikan-ulang.
Module modUjiTitik (kode 8.2) menguji kelas CTitik. Baris 12 menginstansiasi sebuah objek kelas CTitik dan menugaskan 72 sebagai nilai
koordinat x dan 115 sebagai nilai
koordinat y. Baris 15-16 menggunakan
properti X dan Y untuk memperoleh kedua nilai tersebut, dan menampilkannya pada String keluaran. Baris 18-19 mengubah
nilai properti X dan Y, dan baris 22-23 memanggil metode ToString pada kelas CTitik untuk mendapatkan representasi String atas CTitik.
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
|
' Kode 8.2: UjiTitik.vb
' Menguji kelas UjiTitik.
Imports System.Windows.Forms
Module modUjiTitik
Sub Main()
Dim titik As CTitik
Dim keluaran As String
titik = New CTitik(72, 115) ' menginstansiasi
objek CTitik
' menampilkan koordinat
titik via properti X dan Y
keluaran = "koordinat X adalah " &
titik.X & _
vbCrLf & "koordinat Y adalah " &
titik.Y
titik.X = 10 ' menetapkan
koordinat x via properti X
titik.Y = 10 ' menetapkan
koordinat y via properti Y
' menampilkan nilai titik
baru
keluaran &= vbCrLf
& vbCrLf & _
"Lokasi titik yang baru adalah "
& titik.ToString()
MessageBox.Show(keluaran,
"Demonstrasi Kelas Titik")
End Sub ' Main
End Module ' modUjiTitik
|
Gambar 8.4 Keluaran
program pada kode 8.2
Sekarang akan didiskusikan tentang
pewarisan dengan menciptakan dan menguji kelas CLingkaran (kode 8.3), yang secara langsung mewarisi kelas System.Object dan merepresentasikan
sepasang koordinat x-y (pusat lingkaran) dan sebuah radius.
Baris 7-8 mendeklarasikan variabel instans mX,
mY, dan mRadius sebagai data Private.
Layanan Public pada kelas CLingkaran mencakup dua konstruktor CLingkaran (baris 11-27), properti X, Y,
dan Radius (baris 30-70), metode Diameter (baris 73-75), Keliling (baris 78-80), Luas (baris 83-85), dan ToString (baris 88-91).
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
|
' Kode 8.3: Lingkaran.vb
' Kelas CLingkaran memuat
sepasang koordinat x-y dan radius.
Public Class
CLingkaran
' koordinat pusat CLingkaran
Private
mX, mY As Integer
Private
mRadius As Double ' radius
CLingkaran
' konstruktor default
Public
Sub New()
' pemanggilan implisit terhadap
konstruktor Object terjadi di sini
X = 0
Y = 0
Radius = 0
End
Sub ' New
' konstruktor
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer, ByVal nilaiRadius As Double)
' pemanggilan implisit terhadap
konstruktor Object terjadi di sini
X = xNilai
Y = yNilai
Radius = nilaiRadius
End
Sub ' New
' properti X
Public
Property X() As Integer
Get
Return mX
End
Get
Set(ByVal xNilai As Integer)
mX = xNilai ' tidak perlu
validasi
End
Set
End
Property ' X
' properti Y
Public
Property Y() As Integer
Get
Return mY
End
Get
Set(ByVal yNilai As Integer)
mY = yNilai ' tidak perlu
validasi
End
Set
End
Property ' Y
' properti Radius
Public
Property Radius() As Double
Get
Return mRadius
End
Get
Set(ByVal nilaiRadius As Double)
If nilaiRadius > 0 Then
mRadius = nilaiRadius
End If
End
Set
End
Property ' Radius
' menghitung diameter CLingkaran
Public
Function Diameter() As Double
Return
mRadius * 2
End
Function ' Diameter
' menghitung keliling CLingkaran
Public
Function Keliling() As Double
Return
Math.PI * Diameter()
End
Function ' Keliling
' menghitung luas CLingkaran
Public
Function Luas() As Double
Return
Math.PI * mRadius ^ 2
End
Function ' Luas
' menghasilkan representasi String atas
CLingkaran
Public
Overrides Function ToString() As
String
Return
"Pusat = " & "[" & mX & ", " &
mY & "]" & _
"; Radius = " & mRadius
End
Function ' ToString
End Class '
CLingkaran
|
Module modUjiLingkaran (kode 8.4) menguji kelas CLingkaran. Baris 12 menginstansiasi sebuah objek kelas CLingkaran, menugaskan 37 sebagai nilai
koordinat x, 43 sebagai nilai
koordinat y, dan 2.5 sebagai nilai
radius. Baris 15-17 menggunakan properti X,
Y, dan Radius untuk memperoleh nilai-nilai tersebut, kemudian
menampilkannya pada String keluaran.
Baris 20-22 menggunakan properti X, Y, dan Radius pada kelas CLingkaran
untuk mengubah nilai sepasang koordinat x-y dan nilai radius. Properti Radius dipakai untuk memastikan bahwa
variabel anggota Radius tidak dapat
ditugasi nilai negatif. Baris 27 memanggil metode ToString untuk mendapatkan representasi String atas objek CLingkaran,
dan baris 31-38 memanggil metode Diameter,
Lingkaran, dan Luas.
Setelah menuliskan semua kode untuk
kelas CLingkaran (kode 8.4),
perhatikan bahwa kebanyakan potongan kode pada kelas ini mirip, jika tidak
identik, dengan kode pada kelas CTitik.
Sebagai contoh, deklarasi dalam CLingkaran
atas variabel Private mX, mY, dan properti X dan Y identik dengan
yang ada pada kelas CTitik. Di
samping itu, konstruktor kelas CLingkaran
dan metode ToString juga hampir
identik dengan yang ada pada kelas CTitik,
kecuali bahwa konstruktor dan metode ToString
pada kelas CLingkaran mendukung
informasi Radius. Kenyataannya,
tambahan yang ada pada kelas CLingkaran
adalah anggota Private mRadius,
properti Radius, dan metode Diameter, Keliling, dan Luas.
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
|
' Kode 8.4: UjiLingkaran.vb
' Menguji kelas CLingkaran.
Imports System.Windows.Forms
Module modUjiLingkaran
Sub Main()
Dim lingkaran As
CLingkaran
Dim keluaran As String
lingkaran = New CLingkaran(37, 43, 2.5) '
menginstansiasi CLingkaran
' mendapatkan koordinat
x-y awal CLingkaran dan radius
keluaran = "koordinat X adalah " &
lingkaran.X & vbCrLf & _
"koordinat Y adalah " &
lingkaran.Y & vbCrLf & "Radius
adalah " & _
lingkaran.Radius
' menetapkan koordinat x-y
dan radius menjadi nilai baru
lingkaran.X = 2
lingkaran.Y = 2
lingkaran.Radius = 4.25
' menampilkan representasi
String atas CLingkaran
keluaran &= vbCrLf
& vbCrLf & _
"Lokasi dan radius baru atas lingkaran
adalah " & _
vbCrLf &
lingkaran.ToString() & vbCrLf
' menampilkan diameter
CLingkaran
keluaran &= "Diameter adalah " & _
String.Format("{0:F}", lingkaran.Diameter()) &
vbCrLf
' menampilkan keliling
CLingkaran
keluaran &= "Keliling adalah " & _
String.Format("{0:F}", lingkaran.Keliling()) &
vbCrLf
' menampilkan luas
CLingkaran
keluaran &= "Luas adalah " &
String.Format("{0:F}", lingkaran.Luas())
MessageBox.Show(keluaran,
"Demonstrasi Kelas CLingkaran")
End Sub ' Main
End Module ' modUjiLingkaran
|
Gambar 8.5 Keluaran
program pada kode 8.4
Pada contoh berikutnya, akan digunakan
pendekatan yang lebih elegan dan menekankan kegunaan pewarisan. Sekarang, akan
diciptakan dan diuji kelas CLingkaran2
(kode 8.5) yang mewarisi variabel mX
dan mY dan properti X dan Y dari kelas CTitik
(kode 8.1). Kelas CLingkaran2 ini
‘adalah suatu” CTitik, tetapi juga
memuat mRadius (baris 7). Katakunci Inherits pada deklarasi kelas (baris 5)
mengindikasikan pewarisan. Sebagai kelas terderivasi, CLingkaran2 mewarisi semua anggota kelas CTitik, kecuali konstruktornya. Jadi, layanan Public pada CLingkaran2
mencakup dua konstruktor CLingkaran2;
metode-metode Public yang diwarisi
dari kelas CTitik; properti Radius;
dan metode Diameter, Keliling, Luas, dan ToString.
Metode Luas akan dideklarasikan
sebagai Overridable, sehingga kelas
terderivasi (seperti kelas CSilinder,
nanti akan diberikan) dapat mendefinisikan-ulang metode ini.
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
|
' Kode 8.5: Lingkaran2.vb
' Kelas CLingkaran2
mewarisi kelas CTitik.
Public Class
CLingkaran2
Inherits
CTitik ' CLingkaran2 mewarisi kelas CTitik
Private
mRadius As Double ' radius
CLingkaran
' konstruktor default
Public
Sub New()
' pemanggilan implisit terhadap
konstruktor CTitik terjadi di sini
Radius = 0
End
Sub ' New
' konstruktor
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer, ByVal nilaiRadius As Double)
' pemanggilan implisit terhadap
konstruktor CTitik terjadi di sini
mX = xNilai
mY = yNilai
Radius = nilaiRadius
End
Sub ' New
' properti Radius
Public
Property Radius() As Double
Get
Return mRadius
End
Get
Set(ByVal nilaiRadius As Double)
If nilaiRadius > 0 Then
mRadius = nilaiRadius
End If
End
Set
End
Property ' Radius
' menghitung diameter CLingkaran2
Public
Function Diameter() As Double
Return
mRadius * 2
End
Function ' Diameter
' menghitung keliling CLingkaran2
Public
Function Keliling() As Double
Return
Math.PI * Diameter()
End
Function ' Keliling
' menghitung luas CLingkaran2
Public
Function Luas() As Double
Return
Math.PI * mRadius ^ 2
End
Function ' Luas
' menghasilkan representasi String atas
CLingkaran2
Public
Overrides Function ToString() As
String
Return
"Pusat = " & "[" & mX & ", " &
mY & "]" & _
"; Radius = " & mRadius
End
Function ' ToString
End Class '
CLingkaran2
|
Baris 12 dan 20 di dalam konstruktor CLingkaran2 (baris 10-24) memanggil
konstruktor CTitik2 default secara
implisit untuk menginisialisasi porsi kelas-basis (variabel mX dan mY, yang diwarisi dari kelas CTitik)
dari sebuah objek CLingkaran2 dengan
0. Namun, karena konstruktor terparameterisasi (baris 17-24) harus menetapkan
koordinat x-y menjadi nilai tertentu, baris 21-24 mencoba menugaskan
nilai-nilai argumen kepada mX dan mY secara langsung. Meskipun baris
21-22 mencoba menetapkan nilai-nilai mX
dan mY secara eksplisit, baris 20
pertama-tama memanggil konstruktor default CTitik
untuk menginisialisasi kedua variabel tersebut dengan nilai defaultnya.
Kompiler akan menghasilkan error sintaks untuk baris 21-22 (dan baris 60,
dimana metode ToString pada CLingkaran2 mencoba menggunakan
nilai-nilai mX dan mY secara langsung), karena kelas
terderivasi CLingkaran2 tidak
diijinkan untuk mengakses anggota Private
kelas basis CTitik, mX dan mY. Visual Basic secara kaku menegakkan pembatasan dalam mengakses
anggota data Private, bahkan kelas
terderivasinya pun tidak dapat mengakses data Private kelas basis.
Untuk memampukan kelas CLingkaran2 mengakses variabel anggota CTitik, mX dan mY, secara
langsung, kedua variabel tersebut akan dideklarasikan sebagai Protected. Seperti disebutkan
sebelumnya, anggota Protected kelas
basis hanya dapat diakses di dalam kelas basis tersebut atau di dalam salah
satu kelas terderivasinya. Kelas CTitik2
(kode 8.6) memodifikasi kelas CTitik
(kode 8.1), sehingga ia mendeklarasikan variabel mX dan mY sebagai Protected (baris 8) menggantikan 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
|
' Kode 8.6: Titik2.vb
' kelas CTitik2
merepresentasikan pasangan koordinat x-y sebagai Protected
Public Class
CTitik2
' secara implisit mewarisi Object
' koordinat titik
Protected
mX, mY As Integer
' konstruktor default
Public
Sub New()
' pemanggilan implisit terhadap
konstruktor Object terjadi di sini
X = 0
Y = 0
End
Sub ' New
' konstruktor
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer)
' pemanggilan implisit terhadap
konstruktor Object terjadi di sini
X = xNilai
Y = yNilai
End
Sub ' New
' properti X
Public
Property X() As Integer
Get
Return mX
End
Get
Set(ByVal
xNilai As Integer)
mX = xNilai ' tidak perlu
validasi
End
Set
End
Property ' X
' properti Y
Public
Property Y() As Integer
Get
Return mY
End
Get
Set(ByVal yNilai As Integer)
mY = yNilai ' tidak perlu
validasi
End
Set
End
Property ' Y
' menghasilkan representasi String atas
CTitik
Public
Overrides Function ToString() As
String
Return "[" & mX &
", " & mY & "]"
End
Function ' ToString
End Class '
CTitik2
|
Kelas CLingkaran3 (kode 8.7) memodifikasi kelas CLingkaran2 (kode 8.5) untuk mewarisi kelas CTitik2, tidak lagi mewarisi kelas CTitik. Karena kelas CLingkaran3
adalah sebuah kelas yang diwarisi dari kelas CTitik2, kelas CLingkaran3
dapat mengakses variabel Protected
kelas CTitik2, mX dan mY, secara
langsung, dan kompiler tidak lagi menghasilkan error sintaks.
Module modUjiLingkaran3 (kode 8.8) melakukan pengujian identik atas kelas CLingkaran3 seperti pada module modUjiLingkaran (kode 8.4). Perhatikan
bahwa keluaran dari kedua program adalah identik. Kelas CLingkaran diciptakan tanpa menggunakan pewarisan dan kelas CLingkaran3 menggunakan pewarisan;
namun, kedua kelas memberikan fungsionalitas yang sama. Akan tetapi, Anda bisa
mengamati bahwa kode untuk kelas CLingkaran3,
yang memuat 64 baris, lebih pendek dari kode untuk kode CLingkaran, yang memuat 93 baris, karena kelas CLingkaran3 menyerap sebagian fungsionalitasnya dari CTitik2, sedangkan kelas CLingkaran tidak melakukannya.
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
|
' Kode 8.7: Lingkaran3.vb
' Kelas CLingkaran3
mewarisi kelas CTitik2.
Public Class
CLingkaran3
Inherits
CTitik2 ' CLingkaran3 mewarisi kelas CTitik2
Private
mRadius As Double ' radius
CLingkaran
' konstruktor default
Public
Sub New()
' pemanggilan implisit terhadap
konstruktor CTitik terjadi di sini
Radius = 0
End
Sub ' New
' konstruktor
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer, ByVal nilaiRadius As Double)
' pemanggilan implisit terhadap
konstruktor CTitik terjadi di sini
mX = xNilai
mY = yNilai
Radius = nilaiRadius
End
Sub ' New
' properti Radius
Public
Property Radius() As Double
Get
Return mRadius
End
Get
Set(ByVal nilaiRadius As Double)
If nilaiRadius > 0 Then
mRadius = nilaiRadius
End If
End
Set
End
Property ' Radius
' menghitung diameter CLingkaran2
Public
Function Diameter() As Double
Return
mRadius * 2
End
Function ' Diameter
' menghitung keliling CLingkaran2
Public
Function Keliling() As Double
Return
Math.PI * Diameter()
End
Function ' Keliling
' menghitung luas CLingkaran2
Public
Function Luas() As Double
Return
Math.PI * mRadius ^ 2
End
Function ' Luas
' menghasilkan representasi String atas
CLingkaran2
Public
Overrides Function ToString() As
String
Return
"Pusat = " & "[" & mX & ", " &
mY & "]" & _
"; Radius = " & mRadius
End
Function ' ToString
End Class '
CLingkaran3
|
Sayangnya, pendeklarasian variabel
instans sebagai Protected
menyebabkan dua masalah utama. Pertama, objek kelas terderivasi tidak harus
menggunakan properti dalam menetapkan nilai data Protected kelas basis. Oleh karena itu, objek kelas terderivasi
dapat menugaskan nilai tak-valid pada data Protected.
Sebagai contoh, jika variabel Radius
pada CLingkaran3 dideklarasikan
sebagai Protected, maka sebuah objek
kelas terderivasi (misalnya, CSilinder),
dapat menugaskan suatu nilai negatif pada mRadius.
Masalah kedua dalam penggunaan data Protected adalah bahwa metode-metode
kelas terderivasi sangat mungkin akan ditulis bergantung pada implementasi
kelas basis. Pada prakteknya, kelas terderivasi seharusnya hanya bergantung
pada layanan kelas basis (yaitu, metode dan properti tak-Private) dan tidak bergantung pada implementasi kelas basis. Dengan
data Protected di dalam kelas basis,
jika implementasi kelas basis berubah, maka Anda perlu memodifikasi semua kelas
yang diderivasi dari kelas basis itu. Sebagai contoh, jika Anda mengubah nama
variabel mX dan mY menjadi mKoordinatX
dan mKoordinatY, maka Anda juga
harus melakukannya di semua kelas terderivasi. Kelas basis seharusnya dapat
mengubah implementasinya secara bebas, tanpa mengganggu 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
|
' Kode 8.8: UjiLingkaran.vb
' Menguji kelas CLingkaran.
Imports System.Windows.Forms
Module modUjiLingkaran3
Sub Main()
Dim lingkaran As
CLingkaran3
Dim keluaran As String
lingkaran = New CLingkaran3(37, 43, 2.5) '
menginstansiasi CLingkaran3
' mendapatkan koordinat
x-y awal CLingkaran3 dan radius
keluaran = "koordinat X adalah " &
lingkaran.X & vbCrLf & _
"koordinat Y adalah " &
lingkaran.Y & vbCrLf & "Radius
adalah " & _
lingkaran.Radius
' menetapkan koordinat x-y
dan radius menjadi nilai baru
lingkaran.X = 2
lingkaran.Y = 2
lingkaran.Radius = 4.25
' menampilkan representasi
String atas CLingkaran3
keluaran &= vbCrLf
& vbCrLf & _
"Lokasi dan radius baru atas lingkaran
adalah " & _
vbCrLf &
lingkaran.ToString() & vbCrLf
' menampilkan diameter
CLingkaran3
keluaran &= "Diameter adalah " & _
String.Format("{0:F}", lingkaran.Diameter()) & vbCrLf
' menampilkan keliling
CLingkaran3
keluaran &= "Keliling adalah " & _
String.Format("{0:F}", lingkaran.Keliling()) & vbCrLf
' menampilkan luas
CLingkaran
keluaran &= "Luas adalah " &
String.Format("{0:F}", lingkaran.Luas())
MessageBox.Show(keluaran,
"Demonstrasi Kelas CLingkaran3")
End Sub ' Main
End Module ' modUjiLingkaran3
|
Gambar 8.6 Keluaran
program pada kode 8.8
Akan diuji-ulang contoh hirarki
pewarisan sekali lagi; kali ini, akan dicoba untuk menerapkan teknik
pemrograman yang terbaik. Akan digunakan CTitik
(kode 8.1), yang mendeklarasikan variabel mX
dan mY sebagai Private, dan akan ditunjukkan bagaimana kelas terderivasi CLingkaran4 (kode 8.9) dapat memanggil
metode dan properti kelas basis dalam memanipulasi variabel-variabel tersebut.
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
|
' Kode 8.9: Lingkaran4.vb
' Kelas CLingkaran4
mewarisi kelas CTitik.
Public Class
CLingkaran4
Inherits
CTitik ' CLingkaran4 mewarisi kelas CTitik
Private
mRadius As Double ' radius
CLingkaran4
' konstruktor default
Public
Sub New()
' pemanggilan implisit terhadap
konstruktor CTitik terjadi di sini
Radius = 0
End
Sub ' New
' konstruktor
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer, ByVal nilaiRadius As Double)
' menggunakan referensi MyBase ke
konstruktor CTitik secara eksplisit
MyBase.New(xNilai, yNilai)
Radius = nilaiRadius
End
Sub ' New
' properti Radius
Public
Property Radius() As Double
Get
Return mRadius
End
Get
Set(ByVal nilaiRadius As Double)
If nilaiRadius > 0 Then
mRadius = nilaiRadius
End If
End
Set
End
Property ' Radius
' menghitung diameter CLingkaran4
Public
Function Diameter() As Double
Return
mRadius * 2
End
Function ' Diameter
' menghitung keliling CLingkaran4
Public
Function Keliling() As Double
Return
Math.PI * Diameter()
End
Function ' Keliling
'
menghitung luas CLingkaran4
Public
Overridable Function Luas() As Double
Return
Math.PI * mRadius ^ 2
End
Function ' Luas
' menghasilkan representasi String atas
CLingkaran4
Public
Overrides Function ToString() As
String
' menggunakan referensi
MyBase untuk menghasilkan representasi String CTitik
Return
"Pusat= " & MyBase.ToString() & _
"; Radius = " & mRadius
End
Function ' ToString
End Class '
CLingkaran4
|
Pada contoh ini, untuk
mendemonstrasikan pemanggilan implisit dan eksplisit terhadap konstruktor kelas
basis, dicantumkan konstruktor kedua yang memanggil konstruktor kelas basis
secara eksplisit. Baris 17-23 mendeklarasikan konstruktor CLingkaran4 yang memanggil konstruktor CTitik kedua secara eksplisit menggunakan sintaks pemanggilan-konstruktor kelas-basis (yaitu, referensi MyBase diikuti dengan sepasang kurung
yang mengapit argumen-argumen pada konstruktor kelas basis). Pada kasus ini, xNilai dan yNilai dilewatkan untuk menginisialisasi anggota-anggota kelas
basis, mX dan mY. Penyisipan referensi MyBase
diikuti dengan operator dot dilakukan untuk mengakses versi kelas basis dari
metode terkait. Pada konstruktor ini, MyBase.New
memanggil konstruktor CTitik secara
eksplisit (baris 12). Dengan melakukannya secara eksplisit, Anda dapat
menginisialisasi mX dan mY dengan nilai-nilai tertentu, selain
0. Ketika memanggil konstruktor kelas basis secara eksplisit, pemanggilan
tersebut harus menjadi statemen pertama di dalam definisi konstruktor kelas
terderivasi.
Metode ToString pada kelas CLingkaran4
(baris 58-63) mendefinisikan-ulang metode ToString
pada kelas CTitik (baris 54-56 pada
kode 8.1). Seperti didiskusikan sebelumnya, pendefinisian-ulang atas metode ini
dapat dilakukan, karena metode ToString
pada kelas System.Object (kelas
basis untuk kelas CTitik) dideklarasikan
sebagai Overridable. Metode ToString pada kelas CLingkaran4 menampilkan variabel
instans Private, mX dan mY, dari kelas CTitik
dengan memanggil metode ToString
kelas basis (pada kasus ini, metode ToString
kelas CTitik). Pemanggilan ini
dilakukan pada baris 61 melalui ekspresi MyBase.ToString
dan menyebabkan nilai-nilai mX dan mY menjadi bagian dari representasi String atas CLingkaran4. Pendekatan ini adalah praktek pemrograman yang sangat
baik.
Module modUjiLingkaran4 (kode 8.10) melakukan manipulasi identik atas
kelas CLingkaran4, seperti yang
dilakukan module modUjiLingkaran dan
modUjiLingkaran3. Perhatikan bahwa
keluaran dari ketiga module adalah identik. Oleh karena itu, meskipun setiap
kelas “lingkaran” tampak berperilaku identik, kelas CLingkaran4 adalah yang paling baik. Dengan menggunakan pewarisan,
sebuah kelas dikonstruksi terhadap data Private,
dimana di dalamnya perubahan atas implementasi kelas basis CTitik tidak mempengaruhi kelas terderivasi CLingkaran4.
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
|
' Kode 8.10: UjiLingkaran4.vb
' Menguji kelas CLingkaran4.
Imports System.Windows.Forms
Module modUjiLingkaran4
Sub Main()
Dim lingkaran As
CLingkaran4
Dim keluaran As String
lingkaran = New CLingkaran4(37, 43, 2.5) '
menginstansiasi CLingkaran4
' mendapatkan koordinat
x-y awal CLingkaran4 dan radius
keluaran = "koordinat X adalah " &
lingkaran.X & vbCrLf & _
"koordinat Y adalah " &
lingkaran.Y & vbCrLf & "Radius
adalah " & _
lingkaran.Radius
' menetapkan koordinat x-y
dan radius menjadi nilai baru
lingkaran.X = 2
lingkaran.Y = 2
lingkaran.Radius = 4.25
' menampilkan representasi
String atas CLingkaran4
keluaran &= vbCrLf
& vbCrLf & _
"Lokasi dan radius baru atas lingkaran
adalah " & _
vbCrLf &
lingkaran.ToString() & vbCrLf
' menampilkan diameter
CLingkaran4
keluaran &= "Diameter adalah " & _
String.Format("{0:F}", lingkaran.Diameter()) & vbCrLf
' menampilkan keliling
CLingkaran4
keluaran &= "Keliling adalah " & _
String.Format("{0:F}", lingkaran.Keliling()) & vbCrLf
' menampilkan luas
CLingkaran4
keluaran &= "Luas adalah " &
String.Format("{0:F}", lingkaran.Luas())
MessageBox.Show(keluaran,
"Demonstrasi Kelas CLingkaran4")
End Sub ' Main
End Module ' modUjiLingkaran4
|
Gambar 8.7 Keluaran
program pada kode 8.10
Studi
Kasus: Hirarki Pewarisan Tiga-Level
Sekarang akan disajikan contoh
pewarisan tiga-level. Pada bagian sebelumnya, telah dikembangkan kelas CTitik (kode 8.1) dan CLingkaran4 (kode 8.9). Sekarang, akan
disajikan contoh dimana kelas CSilinder
akan diderivasi dari kelas CLingkaran4.
Kelas pertama yang akan digunakan pada
studi kasus ini adalah kelas CTitik
(kode 8.1). Variabel instans CTitik
dideklarasikan Private. Kelas CTitik juga memuat properti X dan Y untuk mengakses mX dan
mY dan metode ToString (yang didefinisikan-ulang oleh CTitik dari kelas Object)
untuk mendapatkan representasi String
atas sepasang koordinat x-y.
Kelas CLingkaran4 (kode 8.9) juga diciptakan, yang mewarisi kelas CTitik. Kelas CLingkaran4 memuat fungsionalitas CTitik, di samping juga menyediakan properti Radius untuk memastikan bahwa anggota mRadius tidak memuat nilai negatif, dan metode Diameter, Lingkaran, Luas, dan ToString. Ingat bahwa metode Luas
dideklarasikan Overridable (baris
53). Seperti dijelaskan sebelumnya, katakunci ini memampukan kelas terderivasi
untuk mendefinisikan-ulang metode kelas basis. Kelas yang diderivasi dari kelas
CLingkaran4 (seperti kelas CSilinder) dapat mendefinisikan-ulang
metode tersebut dan menyediakan implementasi spesifiknya. Sebuah lingkaran
memiliki luas yang dihitung dengan persamaan
dimana r merepresentasikan radius lingkaran. Namun, sebuah silinder
memiliki luas permukaan yang dihitung dengan persamaan yang berbeda:
dimana r merepresentasikan radius
silinder dan h merepresentasikan
tinggi silinder. Oleh karena itu, kelas CSilinder
harus mendefinisikan-ulang metode Luas,
sehingga Anda mendeklarasikan metode Luas
kelas CLingkaran4 sebagai Overridable.
Kode 8.11 merepresentasikan kelas CSilinder, yang mewarisi kelas Lingkaran4 (baris 5). Layanan Public kelas CSilinder mencakup metode-metode yang diwarisi dari CLingkaran4, Diameter, Keliling, Luas, dan ToString; properti Radius yang diwarisi dari CLingkaran4; Properti X
dan Y yang diwarisi secara
tak-langsung dari CTitik;
konstruktor CSilinder, properti Tinggi, dan metode Volume. Metode Luas
(baris 43-45) mendefinisikan-ulang metode Luas
dari kelas CLingkaran4. Perhatikan
bahwa, jika kelas CSilinder
dimaksudkan untuk mendefinisikan-ulang metode Diameter dan Keliling
dari kelas CLingkaran4, maka error
sintaks akan dibangkitkan, karena kelas CLingkaran4
tidak mendeklarasikan kedua metode tersebut sebagai Overridable. Metode ToString
(baris 53-55) mendefinisikan-ulang metode ToString
dari kelas CLingkaran4 untuk
mendapatkan representasi String atas
silinder. Kelas CSilinder juga
mencakup metode Volume (baris 48-50)
untuk menghitung volume silinder. Karena metode Volume tidak dideklarasikan sebagai Overridable, maka semua kelas yang diderivasi dari kelas CSilinder tidak bisa
mendefinisikan-ulang metode ini.
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
|
' Kode 8.11: Silinder.vb
' Kelas CSilinder mewarisi
kelas CLingkaran4.
Public Class
CSilinder
Inherits
CLingkaran4
Protected
mTinggi As Double
' konstruktor default
Public
Sub New()
Tinggi = 0
End
Sub ' New
' konstruktor empat-argumen
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer, ByVal nilaiRadius As Double, _
ByVal
nilaiTinggi As Double)
' pemanggilan eksplisit terhadap
konstruktor CLingkaran4
MyBase.New(xNilai, yNilai, nilaiRadius)
Tinggi = nilaiTinggi ' menetapkan
tinggi CSilinder
End
Sub ' New
' properti Tinggi
Public
Property Tinggi() As Double
Get
Return mTinggi
End
Get
' menetapkan tinggi CSilinder jika
nilai argumen positif
Set(ByVal nilaiTinggi As Double)
If nilaiTinggi >= 0 Then
mTinggi = nilaiTinggi
End If
End
Set
End
Property ' Tinggi
' mendefinisikan-ulang Luas untuk
menghitung luas CSilinder
Public
Overrides Function Luas() As
Double
Return
2 * MyBase.Luas + MyBase.Keliling * mTinggi
End
Function ' Luas
' menghitung volume CSilinder
Public
Function Volume() As Double
Return
MyBase.Luas * mTinggi
End
Function ' Volume
' mengkonversi CSilinder menjadi String
Public
Overrides Function ToString() As
String
Return
MyBase.ToString() & "; Tinggi = " & mTinggi
End
Function ' ToString
End Class '
CSilinder
|
Kode 8.12 adalah sebuah aplikasi modUjiSilinder yang menguji kelas CSilinder. Baris 11 menginstansiasi
sebuah objek kelas CSilinder. Baris
15-17 menggunakan properti X, Y, Radius,
dan Tinggi untuk mendapatkan
informasi tentang objek CSilinder,
karena modUjiSilinder tidak dapat
mereferensi data Private dari kelas CSilinder secara langsung. Baris 20-23
menggunakan properti X, Y, Tinggi,
dan Radius untuk menetapkan-ulang
koordinat x-y CSilinder, tinggi, dan radius. Kelas CSilinder dapat menggunakan properti X dan Y dari kelas CTitik, karena kelas CSilinder mewarisi keduanya secara tak
langsung dari kelas CTitik. Baris 28
memanggil metode ToString untuk
mendapatkan representasi String atas
objek CSilinder. Baris 32-36
memanggil metode Diameter dan Keliling dari objek CSilinder, karena kelas CSilinder mewarisi kedua metode itu
secara langsung dari kelas CLingkaran4
tetapi tidak mendefinisikannya-ulang. Baris 40-44 memanggil metode Luas dan Volume.
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
|
' Kode 8.12: CUjiSilinder.vb
' Menguji kelas CSilinder.
Imports System.Windows.Forms
Module modUjiSilinder
Sub Main()
' menginstansiasi objek
kelas CSilinder
Dim silinder As New
CSilinder(12, 23, 2.5, 5.7)
Dim keluaran As String
' properti untuk mendapatkan
nilai awal koordinat x-y, radius, dan tinggi
keluaran = "koordinat X adalah " &
silinder.X & vbCrLf & _
"koordinat Y adalah " & silinder.Y & vbCrLf &
"Radius adalah " & _
silinder.Radius & vbCrLf & "Tinggi adalah " & silinder.Tinggi
' properti untuk
menetapkan koordinat x-y, radius, dan tinggi yang baru
silinder.X = 2
silinder.Y = 2
silinder.Tinggi = 10
silinder.Radius = 4.25
' mendapatkan koordinat
x-y dan radius yang baru
keluaran &= vbCrLf
& vbCrLf & "Lokasi,
radius " & _
"dan tinggi silinder yang baru adalah" & vbCrLf &
"Pusat = [" & _
silinder.ToString() &
vbCrLf & vbCrLf
' menampilkan diameter
CSilinder
keluaran &= "Diameter adalah " & _
String.Format("{0:F}", silinder.Diameter()) & vbCrLf
' menampilkan keliling
CSilinder
keluaran &= "Keliling adalah " & _
String.Format("{0:F}", silinder.Keliling()) & vbCrLf
' menampilkan luas
CSilinder
keluaran &= "Luas adalah " & _
String.Format("{0:F}", silinder.Luas()) &
vbCrLf
' menampilkan volume
CSilinder
keluaran &= "Volume adalah " & _
String.Format("{0:F}", silinder.Volume())
MessageBox.Show(keluaran,
"Demonstrasi Kelas CSilinder")
End Sub ' Main
End Module ' modUjiSilinder
|
Gambar 8.8 Keluaran
program pada kode 8.12
Konstruktor
dan Finalizer pada Kelas Terderivasi
Seperti yang telah dijelaskan
sebelumnya, penginstansiasian sebuah objek kelas terderivasi menyebabkan rantai
pemanggilan konstruktor, dimana konstruktor kelas terderivasi, sebelum
melakukan tugasnya sendiri, memanggil konstruktor kelas basis secara eksplisit
atau implisit. Sama halnya, jika kelas basis diderivasi dari kelas lain,
konstruktor kelas basis tersebut harus memanggil konstruktor kelas di atas
level hirarkinya, dan seterusnya. Konstruktor terakhir yang dipanggil adalah
konstruktor kelas Object. Setiap
konstruktor kelas basis menginisialisasi setiap variabel instans kelas basis yang
diwarisi oleh objek kelas terderivasi. Sebagai contoh, perhatikan hirarki CTitik/CLingkaran4 dari kode 8.1 dan kode 8.9. Ketika sebuah program
menciptakan objek CLingkaran4, salah
satu konstruktor CLingkaran4 akan
dipanggil. Konstruktor tersebut akan memanggil konstruktor kelas CTitik, yang pada gilirannya akan
memanggil konstruktor kelas Object.
Ketika konstruktor kelas Object
selesai dieksekusi, ia akan mengembalikan kendali program kepada konstruktor
kelas CTitik, yang menginisialisasi
koordinat x-y pada CLingkaran4.
Ketika konstruktor CTitik selesai
dieksekusi, ia mengendalikan kendali program pada konstruktor CLingkaran4, yang menginisialisasi
radius CLingkaran4.
Ketika kolektor sampah menghampus
sebuah objek dari memori, kolektor sampah memanggil metode finalizer objek. Hal
ini akan menyebabkan rantai pemanggilan finalizer, dimana finalizer kelas
terderivasi, finalizer kelas basis langsung, dan finalizer kelas basis tak
langsung dieksekusi dengan urutan terbalik.
Telah didiskusikan pada Bab 7 bahwa
kelas Object mendefinisikan metode Protected Overridable Finalize, yang merupakah finalizer
untuk objek Visual Basic. Karena semua kelas Visual Basic mewarisi kelas Object (secara langsung atau
tak-langsung), kelas-kelas tersebut mewarisi metode Finalize dan dapat mendefikannya-ulang untuk membebaskan sumberdaya
pada objek tertentu. Meskipun tidak dapat ditentukan kapan tepatnya pemanggilan
Finalize terjadi (karena tidak dapat
ditentukan kapan pengumpulan sampah terjadi), Anda masih bisa menspesifikasi
kode yang akan dieksekusi sebelum kolektor sampah menghapus sebuah objek dari
memori.
Contoh berikutnya akan merevisi hirarki
titik-lingkaran dengan mendefiniskan versi kelas CTitik3 (kode 8.13) dan kelas CLingkaran5
(kode 8.14) yang memuat beberapa konstruktor dan finalizer, yang masing-masing
menampilkan sebuah pesan ketika dijalankan.
Kelas CTitik3 (kode 8.13) memuat beberapa fitur yang ditunjukkan pada
kode 8.1, dan Anda memodifikasi dua konstruktor (baris 10-16 dan baris 19-26)
untuk menampilkan sebaris teks ketika dipanggil. Anda juga perlu menambahkan
metode Finalize (baris 29-32) yang
menampilkan keluaran sebaris teks ketika dipanggil. Setiap statemen keluaran
(baris 15, 25, dan 30) menambahkan referensi Me pada string keluaran. Ini secara implisit memanggil metode ToString untuk mendapatkan representasi
String atas koordinat CTitik3. Karena konstruktor tidak
diwariskan, baris 12 dan 22 melakukan pemanggilan implisit terhadap konstruktor
Object. Namun, metode Finalize diwariskan dan
didefinisikan-ulang dari kelas Object,
jadi baris 31 menggunakan referensi MyBase
untuk memanggil metode Finalize
kelas basis Object secara eksplisit.
Jika baris 31 diabaikan, maka metode Finalize
kelas Object tidak akan dipanggil.
Kelas CLingkaran5 (kode 8.14) memuat beberapa fitur dari kode 8.9 dan
Anda memodifikasi dua konstruktor (baris 10-15 dan baris 18-25) untuk
menampilkan sebaris teks ketika dipanggil. Anda juga menambahkan metode Finalize (baris 28-31) yang menampilkan
sebaris teks ketika ia dipanggil. Perhatikan bahwa baris 30 menggunakan MyBase untuk memanggil metode Finalize kelas CTitik3 secara eksplisit. Metode ini tidak dipanggil jika baris ini
diabaikan. Setiap statemen keluaran (baris 14, 24, dan 29) menambahkan
referensi Me pada string keluaran.
Ini secara implisit akan memanggil metode ToString
kelas CLingkaran5 untuk mendapatkan
representasi String atas koordinat dan radius CLingkaran5.
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
|
' Kode 8.13: Titik3.vb
' kelas CTitik3
merepresentasikan pasangan koordinat x-y.
Public Class
CTitik3
' koordinat titik
Private
mX, mY As Integer
' konstruktor default
Public
Sub New()
' pemanggilan implisit terhadap
konstruktor Object terjadi di sini
X = 0
Y = 0
Console.WriteLine("Konstruktor CTitik3: {0}", Me)
End
Sub ' New
' konstruktor
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer)
' pemanggilan implisit terhadap
konstruktor Object terjadi di sini
X = xNilai
Y = yNilai
Console.WriteLine("Konstruktor CTitik3: {0}", Me)
End
Sub ' New
' finalizer mendefinisikan-ulang versi di
dalam kelas Object
Protected
Overrides Sub Finalize()
Console.WriteLine("Finalizer CTitik3: {0}", Me)
MyBase.Finalize()
' memanggil finalizer Object
End
Sub ' Finalize
' properti X
Public Property X() As Integer
Get
Return mX
End Get
Set(ByVal xNilai As Integer)
mX = xNilai ' tidak perlu
validasi
End
Set
End
Property ' X
' properti Y
Public
Property Y() As Integer
Get
Return mY
End
Get
Set(ByVal yNilai As Integer)
mY = yNilai ' tidak perlu
validasi
End Set
End
Property ' Y
' menghasilkan representasi String atas
CTitik3
Public
Overrides Function ToString() As
String
Return
"[" & mX & ", " & mY & "]"
End
Function ' ToString
End Class '
CTitik3
|
Module modKonstruktorDanFinalizer (kode 8.15) mendemonstrasikan urutan
dimana konstruktor dan finalizer dipanggil untuk objek-objek yang merupakan
bagian dari hirarki kelas pewarisan. Metode Main (baris 7-17) mulai menginstansiasi sebuah objek kelas CLingkaran5, kemudian menugaskannya kepada
referensi lingkaran1 (baris 10). Ini
akan memanggil konstruktor CLingkaran5,
yang memanggil konstruktor CTitik3
dengan segera. Kemudian, konstruktor CTitik3
memanggil konstruktor Object. Ketika
konstruktor Object (yang tidak
menampilkan apapun) mengembalikan kendali program pada konstruktor CTitik3, konstruktor CTitik3 menginisialisasi koordinat x-y,
kemudian menampilkan sebuah String
yang mengindikasikan bahwa konstruktor CTitik3
telah dipanggil. Statemen keluaran juga memanggil metode ToString secara implisit (menggunakan referensi Me) untuk mendapatkan representasi String atas objek yang sedang
dikonstruksi. Kemudian, kendali program kembali ke konstruktor CLingkaran5, yang menginisialisasi
radius dan menampilkan koordinat dan radius CLingkaran5 dengan memanggil metode ToString secara implisit.
Perhatikan bahwa dua baris pertama dari
keluaran program ini memuat nilai koordinat x-y dan radius dari CLingkaran5. Ketika mengkonstruksi sebuah objek CLingkaran5, referensi Me yang digunakan di dalam tubuh kedua
konstruktor CLingkaran5 dan CTitik3 menunjuk ke objek CLingkaran5 yang sedang dikonstruksi.
Ketika program memanggil metode ToString
pada sebuah objek, versi ToString
yang dieksekusi adalah selalu versi yang didefinisikan di dalam kelas dari
objek tersebut. Karena referensi Me
menunjuk ke objek CLingkaran5 yang
sedang dikonstruksi, metode ToString
kelas CLingkaran5 dieksekusi bahkan
ketika ToString dipanggil dari tubuh
konstruktor kelas CTitik3. Ketika
konstruktor CTitik3 memanggil metode
ToString untuk objek CLingkaran5 yang sedang dikonstruksi,
program menampilkan 0 untuk nilai mRadius, karena tubuh konstruktor CLingkaran5 belum menginisialisasi mRadius. Ingat bahwa 0 adalah nilai
default untuk variabel Double. Baris
kedua pada keluaran menampilkan nilai mRadius
yang tepat (4.5), karena baris itu
ditampilkan setelah mRadius
diinisialisasi.
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
|
' Kode 8.14: Lingkaran5.vb
' Kelas CLingkaran5
mewarisi kelas CTitik3.
Public Class
CLingkaran5
Inherits
CTitik3 ' CLingkaran4 mewarisi kelas CTitik3
Private
mRadius As Double ' radius
CLingkaran5
' konstruktor default
Public
Sub New()
' pemanggilan implisit terhadap
konstruktor CTitik3 terjadi di sini
Radius = 0
Console.WriteLine("konstruktor CLingkaran5: {0}",
Me)
End
Sub ' New
' konstruktor
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer, ByVal nilaiRadius As Double)
' menggunakan referensi MyBase ke
konstruktor CTitik secara eksplisit
MyBase.New(xNilai, yNilai)
Radius = nilaiRadius
Console.WriteLine("konstruktor CLingkaran5: {0}",
Me)
End
Sub ' New
' finalizer mendefinisikan-ulang versi di
dalam CTitik3
Protected
Overrides Sub Finalize()
Console.WriteLine("finalizer CLingkaran5: {0}", Me)
MyBase.Finalize()
' memanggil finalizer CTitik3
End
Sub ' Finalize
' properti Radius
Public
Property Radius() As Double
Get
Return mRadius
End
Get
Set(ByVal nilaiRadius As Double)
If nilaiRadius > 0 Then
mRadius = nilaiRadius
End If
End
Set
End
Property ' Radius
' menghitung diameter CLingkaran5
Public
Function Diameter() As Double
Return
mRadius * 2
End
Function ' Diameter
' menghitung keliling CLingkaran5
Public
Function Keliling() As Double
Return
Math.PI * Diameter()
End
Function ' Keliling
' menghitung luas CLingkaran5
Public
Overridable Function Luas() As
Double
Return
Math.PI * mRadius ^ 2
End
Function ' Luas
' menghasilkan representasi String atas
CLingkaran5
Public
Overrides Function ToString() As
String
' menggunakan referensi MyBase untuk menghasilkan
representasi String CTitik
Return
"Pusat= " & MyBase.ToString() & _
"; Radius = " & mRadius
End
Function ' ToString
End Class '
CLingkaran5
|
Baris 11 menginstansiasi sebuah objek
kelas CLingkaran5, kemudian
menugaskannya kepada referensi lingkaran2.
Ini akan memulai pemanggilan rantai konstruktor dimana konstruktor CLingkaran5, konstruktor CTitik3, dan konstruktor Object dipanggil. Pada keluaran, perhatikan
bahwa tubuh konstruktor CTitik3
dieksekusi sebelum tubuh konstruktor CLingkaran5.
Ini mendemonstrasikan bahwa konstruktor kelas basis dipanggil terlebih dahulu.
Baris 13-14 menetapkan referensi lingkaran1 dan lingkaran2 menunjuk ke Nothing.
Ini akan menghapus referensi yang menunjuk ke dua objek CLingkaran5 di dalam program. Jadi, kolektor sampah dapat
membebaskan memori yang ditempati oleh kedua objek tersebut. Ingat bahwa Anda
tidak dapat menjamin kapan kolektor sampah dieksekusi. Untuk mendemonstrasikan
pemanggilan finalizer untuk dua objek CLingkaran5,
baris 16 memanggil metode Collect
kelas GC untuk meminta kolektor
sampah agar dijalankan. Perhatikan bahwa finalizer setiap objek CLingkaran5 menampilkan informasi
sebelum memanggil metode Finalize
kelas CTitik3. Terbukti bahwa
finalizer kelas terderivasi dieksekusi lebih dahulu sebelum memanggil finalizer
kelas basis.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
' Kode 8.15: KonstruktorDanFinalizer.vb
' Menampilkan urutan pengeksekusian konstruktor dan finalizer
' kelas basis dan kelas terderivasi.
Module
modKonstruktorDanFinalizer
Sub Main()
Dim lingkaran1, lingkaran2 As
CLingkaran5
lingkaran1 = New CLingkaran5(72, 29, 4.5) '
menginstansiasi objek-objek
lingkaran2 = New CLingkaran5(5, 5, 10)
lingkaran1 = Nothing ' menandai objek untuk
dibuang
lingkaran2 = Nothing
System.GC.Collect() '
meminta kolektor sampah agar dieksekusi
End Sub ' Main
End Module '
modKonstruktorDanFinalizer
|
Konstruktor CTitik3: Pusat= [72, 29]; Radius = 0
konstruktor CLingkaran5: Pusat= [72, 29]; Radius = 4.5
Konstruktor CTitik3: Pusat= [5, 5]; Radius = 0
konstruktor CLingkaran5: Pusat= [5, 5]; Radius = 10
finalizer CLingkaran5: Pusat= [5, 5]; Radius = 10
Finalizer CTitik3: Pusat= [5, 5]; Radius = 10
finalizer CLingkaran5: Pusat= [72, 29]; Radius = 4.5
Finalizer CTitik3: Pusat= [72, 29]; Radius = 4.5
|
Latihan
1.
Banyak program yang ditulis dengan pewarisan dapat
ditulis dengan komposisi, dan sebaliknya. Tulis-ulanglah kelas CTitik, CLingkaran4, dan CSilinder
agar menggunakan komposisi, menggantikan pewarisan. Setelah melakukannya,
teliti dan pertimbangkanlah kedua pendekatan tersebut (pewarisan dan komposisi)
secara khusus (untuk kasus ini) dan secara umum (untuk semua kasus pemrograman
berorientasi objek).
2.
Tulislah sebuah hirarki pewarisan untuk kelas CSegiEmpat, CTrapesium, CPersegipanjang, dan CPersegi. Gunakan CSegiEmpat sebagai kelas basis dalam hirarki. Tulislah sebuah
program yang menginstansiasi objek untuk tiap kelas tersebut; juga tampilkan
pada layar bahwa setiap objek telah diinstansiasi.
3.
Modifikasilah kelas CTitik, CLingkaran4, dan
CSilinder agar memuat metode finalizer
yang didefinisikan-ulang. Kemudian, modifikasi program pada kode 8.15 untuk
mendemonstrasikan urutan pengeksekusian konstruktor dan finalizer.
No comments:
Post a Comment