9.
Pemrograman Berorientasi Objek: Polimorfisme
Pengantar
Diskusi tentang pemrograman
berorientasi objek (PBO) pada bab terdahulu difokuskan pada salah satu komponen
kunci, pewarisan. Pada bab ini, akan dilanjutkan untuk membahas PBO
polimorfisme. Kedua pewarisan dan polimorfisme adalah komponen krusial dalam pengembangan
perangkat-lunak yang kompleks. Polimorfisme memampukan Anda untuk menulis
program yang dapat menangani berbagai varietas kelas yang berelasi dan
memfasilitasi penambahan kelas dan kapabilitas baru ke dalam suatu sistem.
Dengan polimorfisme, dimungkinkan untuk
merancang dan mengimplementasikan sistem yang mudah untuk diperluas atau
dikembangkan. Program dapat memproses objek-objek dari semua kelas di dalam
suatu hirarki kelas yang secara generik dipandang sebagai objek-objek dengan
kelas basis yang sama. Di samping itu, kelas baru dapat ditambahkan dengan
sedikit atau tanpa modifikasi terhadap program, sepanjang kelas baru tersebut
adalah bagian dari hirarki pewarisan yang diproses secara generik oleh program.
Satu-satunya bagian program yang perlu dimodifikasi untuk mengakomodasi kelas
baru adalah komponen program yang memerlukan pengetahuan langsung tentang kelas
baru yang ditambahkan programer ke dalam hirarki. Pada bab ini, akan
didemonstrasikan dua hirarki kelas dan objek-objek dari kedua hirarki akan
dimanipulasi secara polimorfik.
Konversi
Objek-Kelas-Terderivasi Menjadi Objek-Kelas-Basis
Pada bab sebelumnya, telah diciptakan
hirarki kelas titik-lingkaran, dimana kelas CLingkaran mewarisi kelas CTitik.
Program yang memanipulasi objek-objek dari kedua kelas tersebut selalu
menggunakan referensi CTitik untuk
menunjuk ke objek CTitik dan
referensi CLingkaran untuk menunjuk
ke objek CLingkaran. Pada bagian
ini, akan didiskusikan relasi antar kelas di dalam hirarki yang memampukan
sebuah program untuk menugaskan objek kelas terderivasi kepada referensi kelas
basis. Ini merupakan bagian fundamental dalam memproses objek secara
polimorfik. Bagian ini juga akan mendiskusikan casting secara eksplisit antar
tipe di dalam suatu hirarki kelas.
Objek suatu kelas terderivasi dapat
diperlakukan seperti objek kelas basisnya. Ini memampukan berbagai manipulasi
menarik. Sebagai contoh, program dapat menciptakan suatu array yang memuat
beberapa referensi kelas basis yang menunjuk ke beberapa objek kelas
terderivasi. Hal ini diijinkan meskipun objek kelas terderivasi memiliki tipe
data yang berbeda. Namun, kebalikannya tidak berlaku, karena objek kelas basis
bukanlah objek kelas terderivasinya. Sebagai contoh, objek CTitik bukanlah objek CLingkaran.
Contoh pada kode 9.1 – 9.3
mendemonstrasikan penugasan objek kelas terderivasi kepada referensi kelas
basis dan menunjukkan bagaimana melakukan casting terhadap referensi kelas
basis menjadi referensi kelas terderivasi. Kelas CTitik (kode 9.1), yang telah didiskusikan pada Bab 8,
merepresentasikan sepasang koordinat x-y. Kelas CLingkaran (kode 9.2), yang juga telah didiskusikan pada Bab 8,
merepresentasikan sebuah lingkaran dan mewarisi kelas CTitik. Setiap objek CLingkaran
“adalah suatu” CTitik dan juga memiliki
sebuah radius (yang direpresentasikan via variabel mRadius). Metode Luas
akan dideklarasikan sebagai Overridable,
sehingga kelas terderivasi (seperti kelas CSilinder)
dapat menghitung luasnya sendiri. Kelas CUji
(kode 9.3) mendemonstrasikan operasi penugasan dan casting.
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 9.1: Titik.vb
' kelas CTitik
merepresentasikan pasangan koordinat x-y.
Public Class
CTitik
' 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
|
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 9.2: Lingkaran.vb
' Kelas CLingkaran
mewarisi kelas CTitik.
Public Class
CLingkaran
Inherits
CTitik ' CLingkaran 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)
' 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 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
Overridable Function Luas() As Double
Return
Math.PI * mRadius ^ 2
End
Function ' Luas
' menghasilkan representasi String atas
CLingkaran
Public
Overrides Function ToString() As
String
' menggunakan referensi
MyBase untuk menghasilkan representasi String CLingkaran
Return
"Pusat= " & MyBase.ToString() & _
"; Radius = " & mRadius
End
Function ' ToString
End Class '
CLingkaran
|
Kelas CUji (kode 9.3) mendemonstrasikan penugasan referensi kelas
terderivasi kepada referensi kelas basis dan melakukan casting terhadap
referensi kelas basis menjadi referensi kelas terderivasi. Baris 11-12
mendeklarasikan dua referensi CTitik
(titik1 dan titik2) dan dua referensi CLingkaran
(lingkaran1 dan lingkaran2). Baris 14-15 menugaskan sebuah objek CTitik kepada titik1 dan menugaskan sebuah objek CLingkaran kepada lingkaran1.
Baris 17-18 memanggil metode ToString
pada tiap objek, kemudian menampilkan String keluaran agar menunjukkan
nilai-nilai yang digunakan dalam menginisialisasi setiap objek. Karena titik1 adalah sebuah objek CTitik, metode ToString dari titik1
menampilkan objek sebagai sebuah CTitik.
Sama halnya, karena lingkaran1
adalah sebuah objek CLingkaran,
metode ToSting dari lingkaran1 menampilkan objek sebagai
sebuah CLingkaran.
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 9.3: Uji.vb
' Demonstrasi pewarisan dan polimorfisme.
Imports System.Windows.Forms
Class CUji
' demonstrasi relasi
"adalah suatu"
Shared Sub Main()
Dim keluaran As String
Dim titik1, titik2 As
CTitik
Dim lingkaran1, lingkaran2 As
CLingkaran
titik1 = New CTitik(30, 50)
lingkaran1 = New CLingkaran(120, 89, 2.7)
keluaran = "CTitik titik1: " &
titik1.ToString() & _
vbCrLf & "CLingkaran lingkaran1: " &
lingkaran1.ToString()
' menggunakan relasi
adalah-suatu untuk menugaskan CLingkaran kepada referensi CTitik
titik2 = lingkaran1
keluaran &= vbCrLf
& vbCrLf & _
"CLingkaran lingkaran1 (via titik2): " &
titik2.ToString()
' downcast (cast referensi
kelas basis menjadi tipe data
' kelas terderivasi)
titik2 menjadi lingkaran2
lingkaran2 = CType(titik2, CLingkaran) ' hanya
diijinkan via cast
keluaran &= vbCrLf
& vbCrLf & _
"CLingkaran lingkaran1 (via lingkaran2): " &
lingkaran2.ToString()
keluaran &= vbCrLf
& "Luas lingkaran1 (via
lingkaran2): " & _
String.Format("{0:F}", lingkaran2.Luas())
' menugaskan objek CTitik
kepada referensi CLingkaran
If (TypeOf titik1 Is CLingkaran) Then
lingkaran2 = CType(titik1, CLingkaran)
keluaran &= vbCrLf
& vbCrLf & "cast berhasil"
Else
keluaran &= vbCrLf
& vbCrLf & _
"titik1 tidak menunjuk ke sebuah
CLingkaran"
End If
MessageBox.Show(keluaran,
_
"Demonstrasi relasi 'adalah suatu' ")
End Sub ' Main
End Class ' CUji
|
Gambar 9.1 Keluaran
program pada kode 9.3
Baris 21 menugaskan lingkaran1 (sebuah referensi ke objek
kelas terderivasi) kepada titik2
(sebuah referensi kelas basis). Dalam Visual Basic, adalah hal yang dapat
diterima untuk menugaskan sebuah referensi kelas terderivasi kepada sebuah
referensi kelas basis, karena pewarisan memiliki relasi “adalah suatu”. Sebuah CLingkaran
adalah suatu CTitik, karena kelas CLingkaran
mewarisi kelas CTitik. Namun,
penugasan sebuah referensi kelas basis kepada referensi kelas terderivasi
adalah tindakan berbahaya, seperti yang akan didiskusikan nanti.
Baris 23-24 memanggil titik2.ToString dan menampilkan
hasilnya pada keluaran. Ketika
Visual Basic menjumpai Overridable
pada suatu pemanggilan metode (seperti metode ToString), Visual Basic akan menentukan versi metode sesuai yang
akan dipanggil berdasarkan tipe objek, bukan berdasarkan tipe referensi yang
menunjuk objek. Pada kasus ini, referensi titik2
menunjuk ke sebuah objek CLingkaran,
jadi Visual Basic akan memanggil metode ToString
objek CLingkaran (baris 24), bukan
memanggil metode ToString objek CTitik. Keputusan atas metode mana yang
akan dipanggil merupakan salah satu contoh polimorfisme, sebuah konsep yang
akan didiskusikan secara detil pada bab ini. Perhatikan bahwa, jika titik2 mereferensi objek CTitik, bukan objek CLingkaran, maka Visual Basic akan
memanggil metode ToSting objek CTitik.
Pada beberapa bab terdahulu, telah
digunakan metode Convert.ToInt32 dan
Convert.ToDouble untuk mengkonversi
berbagai tipe built-in Visual Basic. Sekarang, dilakukan konversi antar
referensi objek dengan tipe didefinisikan-pengguna. Di sini digunakan metode CType untuk melakukan konversi ini,
yang dikenal dengan cast. Jika cast yang dilakukan valid, program akan
memperlakukan referensi kelas basis sebagai referensi kelas terderivasi. Jika
cast tak-valid, Visual Basic akan melemparkan sebuah InvalidCastException, yang mengindikasikan bahwa operasi cast tidak
diijinkan. Eksepsi akan didiskusikan pada Bab 10.
Baris 28 mengcast titik2, yang sebelumnya menunjuk ke sebuah objek CLingkaran (lingkaran1), menjadi sebuah CLingkaran
dan menugaskan hasilnya pada lingkaran2.
Seperti didiskusikan sebelumnya, cast ini sangat berbahaya jika titik2 sebelumnya mereferensi sebuah CTitik. Baris 30-31 memanggil metode ToString dari objek CLingkaran, yang saat ini ditunjuk oleh
lingkaran2 (perhatikan bahwa baris
keempat pada keluaran mendemonstrasikan bahwa metode ToString dari objek CLingkaran
lah yang dipanggil). Baris 33-34 menghitung Luas dari lingkaran2 dan
memformatnya dengan metode String.Format.
Format “{0:F}” (baris 34)
menspesifikasi pemformatan.
Baris 38 menggunakan metode CType untuk mengcast titik1 menjadi sebuah CLingkaran. Ini merupakan operasi yang
berbahaya, karena titik1 menunjuk ke
sebuah objek CTitik dan objek CTitik bukanlah sebuah CLingkaran. Objek hanya dapat dicast
menjadi tipenya sendiri atau menjadi tipe kelas basisnya. Jika statemen ini
dieksekusi, Visual Basic akan menentukan bahwa titik1 mereferensi sebuah objek CTitik, mengenali operasi cast menjadi CLingkaran adalah hal yang berbahaya, dan mengeluarkan pesan InvalidCastException. Namun, eksekusi
terhadap statemen ini dicegah dengan penggunaan struktur If/Else (baris 37-43). Kondisi pada baris 37 menggunakan operator TypeOf untuk menentukan apakah objek
yang ditunjuk oleh titik1 “adalah
suatu” CLingkaran atau tidak.
Operator TypeOf menentukan tipe
objek yang ditunjuk oleh operandnya. Tipe tersebut kemudian dibandingkan dengan
CLingkaran. Pada contoh ini, titik1 tidak menunjuk ke sebuah CLingkaran, jadi kondisi akan bernilai False, dan baris 41-42 akan menampilkan
keluaran sebagai sebuah String yang mengindikasikan hasil
tersebut. Perhatikan bahwa perbandingan Is
akan bernilai True jika kedua
operand bertipe sama atau jika operand kiri adalah kelas yang diderivasi
(mewarisi) dari kelas pada operand kanan.
Metode
dan Kelas Abstrak
Ketika Anda berpikir tentang kelas
sebagai sebuah tipe, Anda pasti mengasumsikan bahwa program akan menciptakan
objek-objek dengan tipe kelas itu. Namun, ada beberapa kasus dimana sangat
berguna untuk mendefinisikan kelas, sehingga programer tidak berniat untuk
menginstansiasi sembarang objek dari kelas tersebut. Kelas semacam itu
dinamakan kelas abstrak. Karena kelas seperti itu biasanya dipakai sebagai
kelas basis di dalam pewarisan, biasanya kelas semacam itu dinamakan dengan
kelas basis abstrak. Kelas tersebut tidak dapat dipakai untuk menginstansiasi
objek. Kelas abstrak adalah kelas yang tak utuh. Kelas terderivasi harus
mendefinisikan “potongan-potongan” yang hilang dari kelas basis abstrak. Kelas
abstrak biasanya memuat satu atau lebih metode abstrak atau properti abstrak,
yaitu metode dan properti yang tidak menyediakan implementasi. Kelas
terderivasi harus mendefinisikan-ulang metode dan properti abstrak yang
diwarisi agar memampukan objek kelas terderivasi diinstansiasi.
Kegunaan dari kelas abstrak adalah
menyediakan kelas basis yang cocok dan sesuai bagi kelas-kelas terderivasi.
Kelas, yang dapat menginstansiasi objek, dinamakan dengan kelas konkrit. Kelas
semacam itu menyediakan implementasi atas setiap metode dan properti yang
didefinisikan. Anda bisa memiliki sebuah kelas basis abstrak CObjekDuaDimensi dan menderivasi
beberapa kelas konkrit, seperti CPersegi,
CLingkaran, dan CSegitiga. Anda juga dapat memiliki sebuah kelas basis abstrak CObjekTigaDimensi dan menderivasi
beberapa kelas konkrit, seperti CKubik,
CBola, dan CSilinder.
Sebuah kelas dijadikan abstrak dengan
mendeklarasikannya menggunakan katakunci MustInherit.
Suatu hirarki tidak harus memuat kelas kelas MustInherit, tetapi sistem berorientasi objek yang baik selalu
memiliki hirarki kelas dengan kelas basis MustInherit.
Contoh yang baik untuk ini adalah hirarki bangun pada Gambar 8.3. Hirarki
tersebut dimulai dengan kelas basis abstrak MustInherit CBangun.
Pada level berikutnya di dalam hirarki, dimiliki dua kelas basis abstrak MustInherit, sebut saja CBangunDuaDimensi dan CBangunTigaDimensi. Pada level
berikutnya di dalam hirarki, didefinisikan dua kelas konkrit untuk bangun dua
dimensi, CPersegi dan CLingkaran, dan untuk bangun tiga
dimensi, sebut saja CKubik dan CKerucut.
Kelas MustInhenrit harus menspesifikasi metode atau properti abstraknya.
Visual Basic menyediakan katakunci MustOverride
untuk mendeklarasikan metode atau properti abstrak. Metode dan properti MustOverride tidak menyediakan
implementasi. Jika Anda menyediakannya, akan terjadi error sintaks. Setiap
kelas terderivasi harus mendefinisikan-ulang semua metode dan properti MustOverride kelas basis (menggunakan
katakunci Overrides) dan menyediakan
implementasi konkrit atas metode dan properti tersebut. Sembarang kelas yang
memuat metode MustOverride harus
dideklarasikan MustInherit.
Perbedaan antara metode MustOverride
dengan metode Overridable adalah
bahwa metode Overridable memiliki
implementasi dan kelas terderivasi memiliki opsi dalam mendefinisikan-ulang
atau tidak mendefinisikan-ulang metode tersebut; sebaliknya, metode MustOverride tidak menyediakan
implementasi dan kelas terderivasi harus mendefinisikan-ulang metode tersebut.
Meskipun Anda tidak bisa
menginstansiasi objek dari kelas basis MustInherit,
Anda dapat memakai kelas basis MustInherit
untuk mendeklarasikan referensi; referensi itu dapat menunjuk ke instans dari
sembarang kelas konkrit yang diderivasi dari kelas MustInherit. Program dapat menggunakan referensi semacam itu untuk
memanipulasi instans dari kelas terderivasi secara polimorfik.
Sekarang akan didiskusikan satu lagi
aplikasi polimorfisme. Sebuah screen
manager ingin menampilkan pelbagai objek, termasuk beberapa tipe objek baru
yang ditambahkan programer ke dalam sistem. Sistem akan menampilkan berbagai
bangun, seperti CLingkaran, CSegitiga atau CPersegipanjang, yang diderivasi dari kelas MustInherit, CBangun.
Kemudian screen manager menggunakan
referensi kelas basis bertipe CBangun
untuk mengelola objek-objek yang akan ditampilkan. Untuk menggambar sembarang
objek (tidak memandang pada level mana kelas objek berada di dalam hirarki
pewarisan), screen manager
menggunakan sebuah referensi kelas basis untuk memanggil metode Gambar pada objek terkait. Metode Gambar adalah sebuah metode MustOverride di dalam kelas basis CBangun; oleh karena itu, setiap kelas
terderivasi harus mendefinisikan-ulang metode Gambar. Setiap objek CBangun
di dalam hirarki pewarisan mengetahui bagaimana menggambar dirinya sendiri. Screen manager tidak perlu khawatir
tentang tipa setiap objek.
Studi
Kasus: Mewarisi dan Mengimplementasikan Antarmuka
Pada contoh berikutnya (kode 9.4 – 9.8)
akan diuji-ulang hirarki CTitik, CLingkaran, dan CSilinder yang telah dieksplorasi pada Bab 8. Pada contoh ini,
hirarki diawali dengan kelas basis MustInherit,
CBangun (kode 9.4). Hirarki ini
mendemonstrasikan kekuatan dari polimorfisme.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
' Kode 9.4: Bangun.vb
' Demonstrasi hirarki bangun menggunakan kelas MustInherit.
Imports System.Windows.Forms
Public MustInherit Class
CBangun
' menghasilkan luas bangun
Public Overridable Function Luas() As Double
Return 0
End Function ' Luas
' menghasilkan volume bangun
Public Overridable Function Volume() As Double
Return 0
End Function ' Volume
' metode yang harus
didefinisikan-ulang, yang menghasilkan nama bangun
Public MustOverride ReadOnly Property Nama() As String
End Class ' CBangun
|
Kelas CBangun mendefinisikan dua metode konkrit dan satu properti
abstrak. Karena semua bangun memiliki luas dan volume sendiri, maka dicantumkan
metode Luas (baris 9-11) dan Volume (baris 14-16), yang menghasilkan
luas dan volume bangun. Volume dari bangun dua dimensi selalu bernilai nol,
sedangkan volume bangun tiga dimensi selalu bernilai tak-nol positif. Dalam
kelas CBangun, metode Luas dan Volume menghasilkan nilai balik nol, secara default. Programer
dapat mendefinisikan-ulang kedua definisi tersebut di dalam kelas terderivasi.
Properti Nama (baris 19)
dideklarasikan sebagai MustOverride,
sehingga kelas terderivasi harus mendefinisikan-ulang properti ini agar menjadi
kelas konkrit.
Kelas CTitik2 (kode 9.5) mewarisi kelas MustInherit, CBangun,
dan mendefinisikan-ulang properti MustOverride,
Nama, yang menjadikan CTitik2 sebagai kelas konkrit. Luas dan
volume suatu titik bernilai nol, sehingga kelas CTitik2 tidak mendefinisikan-ulang metode Luas dan Volume. Baris
59-65 mengimplementasikan properti Nama.
Jika Anda tidak menyediakan implementasi ini, maka kelas CTitik2 akan menjadi kelas abstrak yang memerlukan katakunci MustInherit pada baris pertama dalam
definisi kelas.
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
|
' Kode 9.5: Titik2.vb
' kelas CTitik2
merepresentasikan pasangan koordinat x-y.
Public Class
CTitik2
Inherits
CBangun ' CTitik2 mewarisi kelas MustInherit CBangun
' 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
CTitik2
Public
Overrides Function ToString() As
String
Return
"[" & mX & ", " & mY & "]"
End
Function ' ToString
' implementasi properti MustOverride dari
kelas CBangun
Public
Overrides ReadOnly Property Nama() As
String
Get
Return "CTitik2"
End
Get
End
Property ' Nama
End Class '
CTitik2
|
Kode 9.6 mendefinisikan kelas CLingkaran2, yang mewarisi kelas CTitik2. Kelas CLingkaran2 memuat variabel anggota mRadius dan menyediakan properti Radius (baris 26-40) untuk mengakses mRadius. Perhatikan bahwa properti Radius tidak dideklarasikan sebagai Overridable, sehingga kelas yang diderivasi dari kelas ini tidak
dapat mendefinisikan-ulang properti ini. Sebuah lingkaran memiliki volume nol,
jadi Anda tidak perlu mendefinisikan-ulang metode kelas basis Volume. CLingkaran2 bisa saja mewarisi metode ini dari kelas CTitik2, yang mewarisi metode tersebut
dari CBangun. Tetapi, lingkaran
memiliki luas, sedangkan CTitik2
tidak memiliki luas, sehingga CLingkaran2
mendefinisikan-ulang metode Luas
dari kelas CBangun (baris 53-55).
Properti Nama (baris 66-72) dari
kelas CLingkaran2
mendefinisikan-ulang properti Nama
dari kelas CTitik2.
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
|
' Kode 9.6: Lingkaran2.vb
' Kelas CLingkaran2
mewarisi kelas CTitik.
Public Class
CLingkaran2
Inherits
CTitik2 ' CLingkaran2 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)
' 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 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
Overrides Function Luas() As
Double
Return
Math.PI * mRadius ^ 2
End
Function ' Luas
' menghasilkan representasi String atas
CLingkaran2
Public
Overrides Function ToString() As
String
' menggunakan referensi MyBase untuk menghasilkan
representasi String CLingkaran2
Return
"Pusat= " &
MyBase.ToString() & _
"; Radius = " & mRadius
End
Function ' ToString
' mendefinisikan-ulang properti Nama dari
kelas CTitik2
Public Overrides ReadOnly Property
Nama() As String
Get
Return "CLingkaran2"
End
Get
End
Property ' Nama
End Class '
CLingkaran2
|
Kode 9.7 mendefinisikan kelas CSilinder2 yang mewarisi kelas CLingkaran2. Kelas CSilinder2 memuat variabel anggota mTinggi dan properti Tinggi
(baris 27-42) untuk mengakses mTinggi.
Perhatikan bahwa properti Tinggi
tidak dideklarasikan sebagai Overridable,
jadi semua kelas yang diderivasi dari kelas CSilinder tidak dapat mendefinisikan-ulang properti ini. Sebuah
silinder memiliki perhitungan luas dan volume yang berbedar dari lingkaran,
jadi kelas ini mendefinisikan-ulang metode Luas
(baris 45-47) untuk menghitung luas permukaan silinder
dan mendefinisikan metode Volume (baris 50-52). Properti Nama
(baris 60-62) mendefinisikan-ulang properti Nama dari kelas CLingkaran2.
Jika kelas ini tidak mendefinisikan-ulang properti Nama, maka kelas ini akan mewarisi properti Nama dari kelas CLingkaran2,
yang secara salah akan menampilkan “CLingkaran2”.
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
|
' Kode 9.7: Silinder2.vb
' Kelas CSilinder2
mewarisi kelas CLingkaran2.
Public Class
CSilinder2
Inherits
CLingkaran2 ' CSilinder2 mewarisi
kelas CLingkaran2
Protected
mTinggi As Double
' konstruktor default
Public
Sub New()
' pemanggilan implisit terhadap
konstruktor CLingkaran2 terjadi di sini
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 CLingkaran2
MyBase.New(xNilai, yNilai, nilaiRadius)
Tinggi = nilaiTinggi ' menetapkan
tinggi CSilinder2
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 CSilinder2
Public
Overrides Function Luas() As
Double
Return
2 * MyBase.Luas + MyBase.Keliling * mTinggi
End
Function ' Luas
' menghitung volume CSilinder2
Public
Overrides Function Volume() As
Double
Return
MyBase.Luas * mTinggi
End
Function ' Volume
' mengkonversi CSilinder2 menjadi String
Public
Overrides Function ToString() As
String
Return
MyBase.ToString() & ";
Tinggi = " & mTinggi
End
Function ' ToString
' mendefinisikan-ulang properti Nama dari
kelas CLingkaran2
Public
Overrides ReadOnly Property Nama() As
String
Get
Return "CSilinder2"
End
Get
End
Property ' Nama
End Class '
CSilinder2
|
Kode 9.8 mendefinisikan kelas CUji2, memiliki metode Main untuk menciptakan sebuah objek
dari tiap kelas konkrit dan memanipulasi objek-objek tersebut secara polimorfik
menggunakan array yang memuat beberapa referensi CBangun. Baris 11-13 menginstansiasi objek CTitik2 (titik), objek CLingkaran2 (lingkaran), dan objek CSilinder2
(silinder). Selanjutnya, baris 16
menginstansiasi array arrayBangun,
yang memua tiga referensi CBangun.
Baris 19 menugaskan referensi titik
untuk menunjuk ke elemen array arrayBangun(0),
baris 22 menugaskan referensi lingkaran
untuk menunjuk ke elemen array arrayBangun(1),
dan baris 25 menugaskan referensi silinder
untuk menunjuk ke elemen array arrayBangun(2).
Ketiga penugasan ini mungkin dilakukan, karena sebuah CTitik2 adalah sebuah CBangun,
sebuah CLingkaran2 adalah sebuah CBangun, dan sebuah CSilinder2 adalah sebuah CBangun. Oleh karena itu, Anda dapat
menugaskan instans dari kelas-kelas terderivasi, CTitik2, CLingkaran2,
dan CSilinder2 kepada referensi
kelas basis CBangun.
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
|
' Kode 9.8: Uji2.vb
' Demonstrasi polimorfisme di dalam hirarki Titik-Lingkaran-Silinder.
Imports System.Windows.Forms
Class CUji2
Shared Sub Main()
' instansiasi objek
CTitik2, c, dan CSilinder2
Dim titik As New
CTitik2(7, 11)
Dim lingkaran As New
CLingkaran2(22, 8, 3.5)
Dim silinder As New
CSilinder2(10, 10, 3.3, 10)
' instansiasi array yang
memuat tiga referensi kelas basis
Dim arrayBangun(2) As
CBangun
' arrayBangun(0) menunjuk
ke objek CTitik2
arrayBangun(0) = titik
' arrayBangun(1) menunjuk
ke objek CLingkaran2
arrayBangun(1) = lingkaran
' arrayBangun(2) menunjuk
ke objek CSilinder2
arrayBangun(2) = silinder
Dim keluaran As String
= titik.Nama & ": " & _
titik.ToString() &
vbCrLf & lingkaran.Nama & ": " & _
lingkaran.ToString() &
vbCrLf & silinder.Nama & _
": " &
silinder.ToString()
Dim bangun As CBangun
' menampilkan nama, luas,
dan volume untuk setiap objek di dalam
' arrayBangun secara
polimorfik
For Each bangun In
arrayBangun
keluaran &= vbCrLf
& vbCrLf & bangun.Nama
& ": " & _
bangun.ToString()
& vbCrLf & "Luas = " & _
String.Format("{0:F}", bangun.Luas) & vbCrLf & _
"Volume = " &
String.Format("{0:F}", bangun.Volume)
Next
MessageBox.Show(keluaran,
"Demonstrasi Polimorfisme")
End Sub ' Main
End Class ' CUji2
|
Gambar 9.2 Keluaran
program pada kode 9.8
Baris 27-30 memanggil properti Nama dan metode ToString untuk objek titik,
lingkaran, dan silinder. Properti Nama
menghasilkan nama kelas objek dan metode ToString
menghasilkan representasi String
atas objek (sepasang koordinat x-y, radius, dan tinggi, tergantung pada
tiap tipe objek). Perhatikan bahwa baris 27-30 menggunakan referensi kelas
terderivasi untuk memanggil metode dan properti dari setiap objek kelas
terderivasi.
Sebaliknya, struktur For Each (baris 36-41) menggunakan
referensi kelas basis CBangun untuk
memanggil metode dan properti setiap objek kelas terderivasi. Struktur For Each memanggil properti Nama dan metode ToString, Luas dan Volume untuk tiap referensi CBangun di dalam arrayBangun. Properti dan metode dipanggil pada tiap objek di dalam
arrayBangun.
Kelas
NotInheritable dan Metode NotOverridable
Sebuah kelas yang dideklarasikan NotInheritable tidak dapat dijadikan
kelas basis. Programer menggunakan fitur ini untuk mencegah pewarisan melebihi
kelas NotInheritable di dalam
hirarki. Kelas NotInheritable
berlawanan dengan kelas MustInherit.
Kelas NotInheritable adalah sebuah
kelas konkrit yang tidak dapat berperan sebagai kelas basis, sedangkan kelas MustInherit adalah sebuah kelas basis
yang dapat berperan sebagai kelas basis.
Sebuah metode yang dideklarasikan Overridable di dalam kelas basis dapat
dideklarasikan NotOverridable di
dalam kelas terderivasi. Ini akan mencegah pendefinisian-ulang metode tersebut
di dalam semua kelas yang diderivasi dari kelas terderivasi tersebut. Semua
kelas yang diderivasi dari kelas yang memuat metode NotOverridable harus menggunakan implementasi metode pada kelas
tersebut. Metode yang dideklarasikan Shared
dan metode yang dideklarasikan Private
secara implisit adalah NotOverridable.
Studi
Kasus: Sistem Penggajian Menggunakan Polimorfisme
Akan digunakan kelas abstrak
(dideklarasikan sebagai MustInherit),
metode abstrak (dideklarasikan sebagai MustOverride)
dan polimorfisme untuk melakukan berbagai perhitungan penggajian yang berbeda
untuk pelbagai tipe karyawan. Akan dimulai dengan menciptakan sebuah kelas
basis CKaryawan. Empat kelas yang
diderivasi dari CKaryawan adalah CBoss (digaji tetap secara mingguan,
tanpa memandang jumlah jam kerja), CKaryawanKomisi
(dengan gaji pokok tetap ditambah dengan persentasi penjualan), CKaryawanItem (digaji tiap item yang
dihasilkan), dan CKaryawanPerjam
(digaji berdasarkan jumlah jam kerja dengan “satu setengah kali” gaji untuk
lembur). Pada contoh ini, semua kelas yang mewarisi CKaryawan dideklarasikan sebagai NotInheritable, karena tidak dimaksudkan untuk menderivasi kelas
dari kelas-kelas tersebut.
Aplikasi harus menentukan penghasilan
mingguan untuk semua tipe karyawan, sehingga setiap kelas yang diderivasi dari CKaryawan memerlukan metode Penghasilan. Namun, setiap kelas
terderivasi menggunakan perhitungan yang berbeda dalam menentukan penghasilan untuk
tipe karyawan tertentu. Oleh karena itu, metode Penghasilan dideklarasikan sebagai MustOverride di dalam kelas CKaryawan
dan kelas CKaryawan dideklarasikan
sebagai kelas MustInherit. Setiap
kelas terderivasi akan mendefinisikan-ulang metode Penghasilan agar dapat menghitung penghasilan tiap tipe karyawan.
Untuk menghitung penghasilan karyawan,
program dapat menggunakan sebuah referensi kelas basis yang menunjuk ke objek
kelas terderivasi dan memanggil metode Penghasilan.
Dalam sistem penggajian, pelbagai objek CKaryawan
dapat direferensi oleh elemen-elemen individual di dalam sebuah array yang
memuat beberapa referensi CKaryawan.
Program kemudian akan menjelajah array, elemen demi elemen, menggunakan
referensi CKaryawan untuk memanggil
metode Penghasilan yang sesuai untuk
setiap objek.
Anda bisa melihat kelas CKaryawan (kode 9.9). Anggora-anggota Public mencakup sebuah konstruktor
(baris 10-15) yang mengambil sebagai argumen nama pertama dan nama akhir
seorang karyawan; properti NamaPertama
(baris 18-28) dan NamaAkhir (baris
31-41); metode ToString (baris
44-46) yang menghasilkan nilai balik berupa nama pertama dan nama akhir yang
dipisahkan dengan spasi; dan metode MustOverride,
Penghasilan (baris 50). Katakunci MustInherit (baris 4) mengindikasikan
bahwa kelas CKaryawan adalah kelas
abstrak; jadi, ia tidak dapat dipakai untuk menginstansiasi objek CKaryawan. Metode Penghasilan dideklarasikan sebagai MustOverride, sehingga kelas CKaryawan
tidak menyediakan implementasi metode tersebut. Semua kelas yang diderivasi
secara langsung dari kelas CKaryawan,
kecuali kelas terderivasi abstrak, harus mendefinisikan metode ini. Metode Penghasilan adalah abstrak di dalam
kelas CKaryawan, karena Anda tidak
dapat menghitung penghasilan secara umum untuk semua tipe karyawan.
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
|
' Kode 9.9: Karyawan.vb
' Kelas basis abstrak
untuk semua kelas terderivasi.
Public MustInherit Class CKaryawan
Private
mNamaPertama As String
Private
mNamaAkhir As String
' konstruktor
Public
Sub New(ByVal nilaiNamaPertama
As String, _
ByVal
nilaiNamaAkhir As String)
NamaPertama = nilaiNamaPertama
NamaAkhir = nilaiNamaAkhir
End
Sub ' New
' properti NamaPertama
Public
Property NamaPertama() As String
Get
Return mNamaPertama
End
Get
Set(ByVal nilaiNamaPertama As String)
mNamaPertama = nilaiNamaPertama
End
Set
End
Property ' NamaPertama
' properti NamaAkhir
Public
Property NamaAkhir() As String
Get
Return mNamaAkhir
End
Get
Set(ByVal nilaiNamaAkhir As String)
mNamaAkhir = nilaiNamaAkhir
End
Set
End
Property ' NamaAkhir
' mendapatkan representasi String atas
karyawan
Public
Overrides Function ToString() As
String
Return
mNamaPertama & " " & mNamaAkhir
End
Function ' ToString
' metode abstrak harus diimplementasikan
untuk setiap kelas terderivasi
' dari CKaryawan dalam menghitung
penghasilan spesifik
Public
MustOverride Function Penghasilan() As
Decimal
End Class '
CKaryawan
|
Kelas CBoss (kode 9.10) mewarisi CKaryawan.
Konstruktor kelas CBoss (baris
10-15) menerima sebagai argumen nama pertama, nama akhir, dan gaji. Konstruktor
melewatkan nama pertama dan nama akhir kepada konstruktor CKaryawan (baris 13), yang menginisialisasi anggota mNamaPertama dan mNamaAkhir, yang merupakan bagian kelas basis di dalam objek kelas
terderivasi. Metode-metode lain yang dimuat di dalam CBoss mencakup metode Penghasilan
(baris 36-38), yang mendefinisikan perhitungan dari penghasilan seorang boss,
dan metode ToString (baris 41-43),
yang menghasilkan nilai balik berupa sebuah String yang mengindikasikan tipe karyawan (yaitu, “CBoss: “) dan nama boss. Kelas CBoss juga menyertakan properti GajiMingguan (baris 18-33), yang
menetapkan dan memperoleh nilai variabel anggota mGaji. Perhatikan bahwa properti ini hanya memastikan bahwa mGaji tidak dapat memuat nilai negatif.
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
|
' Kode 9.10: Boss.vb
' Kelas CBoss mewarisi CKaryawan.
Public NotInheritable Class CBoss
Inherits CKaryawan
Private mGaji As Decimal
' konstruktor untuk CBoss
Public Sub New(ByVal
nilaiNamaPertama As String, _
ByVal nilaiNamaAkhir As
String, ByVal nilaiGaji As Decimal)
MyBase.New(nilaiNamaPertama,
nilaiNamaAkhir)
GajiMingguan = nilaiGaji
End Sub ' New
' properti GajiMingguan
Public Property GajiMingguan() As Decimal
Get
Return mGaji
End Get
Set(ByVal
nilaiGajiBoss As Decimal)
' validasi mGaji
If nilaiGajiBoss > 0 Then
mGaji =
nilaiGajiBoss
End If
End Set
End Property ' GajiMingguan
' mendefinisikan-ulang metode
kelas basis untuk menghitung penghasilan Boss
Public Overrides Function Penghasilan() As Decimal
Return GajiMingguan
End Function ' Penghasilan
' menghasilkan nama Boss
Public Overrides Function ToString() As String
Return "CBoss:
" & MyBase.ToString()
End Function ' ToString
End Class ' CBoss
|
Kelas CKaryawanKomisi (kode 9.11) juga mewarisi kelas CKaryawan. Konstruktor untuk kelas ini
(baris 12-21) menerima sebagai argumen nama pertama, nama akhir, gaji, komisi,
dan kuantitas item yang terjual. Baris 17 melewatkan nama pertama dan nama
akhir kepada konstruktor CKaryawan.
Kelas KaryawanKomisi juga menyediakan
properti Gaji (baris 24-39), Komisi (baris 42-57), dan Kuantitas (baris 60-75); metode Penghasilan (baris 78-80), yang
menghitung gaji karyawan; dan metode ToString
(baris 83-85), yang menghasilkan nilai balik berupa sebuah String yang mengindikasikan tipe karyawan (yaitu, “CKaryawanKomisi: “) dan nama karyawan.
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
|
' Kode 9.11:
KaryawanKomisi.vb
' Implementasi CKaryawan
untuk karyawan komisi.
Public NotInheritable Class CKaryawanKomisi
Inherits
CKaryawan
Private
mGaji As Decimal ' gaji pokok per
minggu
Private
mKomisi As Decimal ' komisi per
item yang terjual
Private
mKuantitas As Integer ' total item
terjual
' konstruktor untuk kelas CKaryawanKomisi
Public
Sub New(ByVal nilaiNamaPertama
As String, _
ByVal
nilaiNamaAkhir As String, ByVal
nilaiGaji As Decimal, _
ByVal
nilaiKomisi As Decimal, _
ByVal
nilaiKuantitas As Integer)
MyBase.New(nilaiNamaPertama, nilaiNamaAkhir)
Gaji = nilaiGaji
Komisi = nilaiKomisi
Kuantitas = nilaiKuantitas
End
Sub ' New
' properti Gaji
Public
Property Gaji() As Decimal
Get
Return mGaji
End
Get
Set(ByVal nilaiGaji As Decimal)
' validasi mGaji
If nilaiGaji > 0 Then
mGaji = nilaiGaji
End If
End
Set
End
Property ' Gaji
' properti Komisi
Public
Property Komisi() As Decimal
Get
Return mKomisi
End
Get
Set(ByVal nilaiKomisi As Decimal)
' validasi mKomisi
If nilaiKomisi > 0 Then
mKomisi = nilaiKomisi
End If
End
Set
End
Property ' Komisi
' properti Kuantitas
Public
Property Kuantitas() As Integer
Get
Return mKuantitas
End
Get
Set(ByVal nilaiKuantitas As Integer)
' validasi mKuantitas
If nilaiKuantitas > 0 Then
mKuantitas = nilaiKuantitas
End If
End
Set
End
Property ' Kuantitas
' mendefinisikan-ulang metode untuk
menghitung penghasilan KaryawanKomisi
Public
Overrides Function Penghasilan() As
Decimal
Return
Gaji + Komisi * Kuantitas
End
Function ' Penghasilan
' menghasilkan nama karyawan komisi
Public
Overrides Function ToString() As
String
Return
"CKaryawanKomisi: "
& MyBase.ToString()
End
Function ' ToString
End Class '
CKaryawanKomisi
|
Kelas CKaryawanItem (kode 9.12) mewarisi kelas CKaryawan. Konstruktor kelas ini (baris 11-19) menerima sebagai
argumen nama pertama, nama akhir, gaji per item, dan kuantitas item yang
dihasilkan. Baris 16 kemudian melewatkan nama pertama dan nama akhir kepada
konstruktor kelas basis CKaryawan.
Kelas CKaryawanItem juga menyediakan
properti GajiPerItem (baris 22-37)
dan Kuantitas (baris 40-55); metode Penghasilan (baris 58-60), yang
menghitung penghasilan karyawan per item; dan metode ToString (baris 63-65), yang menghasilkan nilai balik berupa sebuah
String yang mengindikasikan tipe
karyawan (yaitu, “CKaryawanItem: “)
dan nama karyawan item.
Kelas CKaryawanPerJam (kode 9.13) mewarisi kelas CKaryawan. Konstruktor untuk kelas ini (baris 11-18) menerima
sebagai argumen nama pertama, nama akhir, gaji, dan jumlah jam kerja. Baris 15
melewatkan nama pertama dan nama akhir kepada konstruktor kelas basis CKaryawan. Kelas CKaryawanPerJam juga menyediakan properti GajiPerJam (baris 21-36) dan Jam
(baris 39-54); metode Penghasilan
(baris 57-67), yang menghitung penghasilan karyawan per jam; dan metode ToString (baris 70-72) yang
menghasilkan nilai balik berupa sebuah String
yang mengindikasikan tipe karyawan (yaitu, “CKaryawanPerJam: “) dan nama karyawan per jam.
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
|
' Kode 9.12:
KaryawanItem.vb
' Kelas KaryawanItem
diderivasi dari CKaryawan.
Public NotInheritable Class CKaryawanItem
Inherits
CKaryawan
Private
mJumlahPerItem As Decimal ' gaji
per item
Private
mKuantitas As Integer ' kuantitas
per minggu
' konstruktor untuk CKaryawanItem
Public
Sub New(ByVal nilaiNamaPertama
As String, _
ByVal
nilaiNamaAkhir As String, _
ByVal
nilaiGajiPerItem As Decimal, _
ByVal
nilaiKuantitas As Integer)
MyBase.New(nilaiNamaPertama, nilaiNamaAkhir)
GajiPerItem = nilaiGajiPerItem
Kuantitas = nilaiKuantitas
End
Sub ' New
' properti GajiPerItem
Public
Property GajiPerItem() As Decimal
Get
Return mJumlahPerItem
End
Get
Set(ByVal nilaiGajiPerItem As Decimal)
' validasi mJumlahPerItem
If nilaiGajiPerItem > 0 Then
mJumlahPerItem =
nilaiGajiPerItem
End If
End Set
End
Property ' GajiPerItem
' properti Kuantitas
Public
Property Kuantitas() As Integer
Get
Return mKuantitas
End
Get
Set(ByVal nilaiKuantitas As Integer)
' validasi mKuantitas
If nilaiKuantitas > 0 Then
mKuantitas = nilaiKuantitas
End If
End
Set
End
Property ' Kuantitas
' mendefinisikan-ulang metode kelas basis untuk
menghitung penghasilan KaryawanItem
Public
Overrides Function Penghasilan() As
Decimal
Return
Kuantitas * GajiPerItem
End
Function ' Penghasilan
' menghasilkan nama karyawan item
Public
Overrides Function ToString() As
String
Return
"CKaryawanItem: " &
MyBase.ToString()
End
Function ' ToString
End Class '
CKaryawanItem
|
Metode Main (baris 8-50) dari kelas CUji
(kode 9.14) mendeklarasikan referensi CKaryawan,
karyawan (baris 9). Setiap tipe
karyawan ditangani dengan cara yang sama di dalam Main, sehingga yang didiskusikan hanya tentang manipulasi objek CBoss.
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
|
' Kode 9.13:
KaryawanPerJam.vb
' Implementasi CKaryawan
untuk karyawan per jam.
Public NotInheritable Class CKaryawanPerJam
Inherits
CKaryawan
Private
mGaji As Decimal ' gaji per jam
Private
mJamKerja As Double ' jam kerja
selama seminggu
' konstruktor untuk kelas CKaryawanPerJam
Public
Sub New(ByVal nilaiNamaPertama
As String, _
ByVal
nilaiNamaAkhir As String, _
ByVal
nilaiGaji As Decimal, ByVal nilaiJam As Double)
MyBase.New(nilaiNamaPertama, nilaiNamaAkhir)
GajiPerJam = nilaiGaji
Jam = nilaiJam
End
Sub ' New
' properti GajiPerJam
Public
Property GajiPerJam() As Decimal
Get
Return mGaji
End
Get
Set(ByVal nilaiGajiPerJam As Decimal)
' validasi mGaji
If nilaiGajiPerJam > 0 Then
mGaji = nilaiGajiPerJam
End If
End
Set
End Property ' GajiPerJam
' properti Jam
Public
Property Jam() As Double
Get
Return mJamKerja
End
Get
Set(ByVal nilaiJam As Double)
' validasi mJamKerja
If nilaiJam > 0 Then
mJamKerja = nilaiJam
End If
End
Set
End
Property ' Jam
' mendefinisikan-ulang metode kelas basis untuk
menghitung penghasilan KaryawanPerJam
Public
Overrides Function Penghasilan() As
Decimal
' menghitung untuk "satu dan
setengah"
If
mJamKerja <= 40 Then
Return Convert.ToDecimal(mGaji * mJamKerja)
Else
Return Convert.ToDecimal((mGaji * mJamKerja) + _
(mJamKerja - 40) * 1.5 * mGaji)
End
If
End
Function ' Penghasilan
' menghasilkan nama karyawanperjam
Public
Overrides Function ToString() As
String
Return
"CKaryawanPerJam: "
& MyBase.ToString()
End
Function ' ToString
End Class '
CKaryawanPerJam
|
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 9.14: Uji.vb
' Menampilkan penghasilan
untuk tiap CKaryawan.
Imports
System.Windows.Forms
Class CUji
Shared
Sub Main()
Dim
karyawan As CKaryawan ' referensi
kelas basis
Dim
keluaran As String
Dim
boss As CBoss = New
CBoss("DJumanggal",
"Sianipar", 800)
Dim
karyawanKomisi As CKaryawanKomisi
= _
New
CKaryawanKomisi("Undur",
"Siahaan", 400, 3, 150)
Dim
karyawanItem As CKaryawanItem = _
New
CKaryawanItem("Robert",
"Sianipar", _
Convert.ToDecimal(2.5), 200)
Dim
karyawanPerJam As CKaryawanPerJam
= _
New
CKaryawanPerJam("Rico",
"Sianipar", _
Convert.ToDecimal(13.75), 40)
' memakai referensi yang menunjuk ke
sebuah CBoss
karyawan = boss
keluaran &= GetString(karyawan)
& boss.ToString() & _
" bergaji sebesar " &
boss.Penghasilan.ToString("C") & vbCrLf & vbCrLf
' menggunakan referensi yang menunjuk
ke CKaryawanKomisi
karyawan = karyawanKomisi
keluaran &= GetString(karyawan)
& _
karyawanKomisi.ToString() &
" bergaji sebesar "
& _
karyawanKomisi.Penghasilan.ToString("C") & vbCrLf & vbCrLf
' memakai referensi yang menunjuk ke
sebuah CKaryawanItem
karyawan = karyawanItem
keluaran &= GetString(karyawan)
& karyawanItem.ToString() & _
" bergaji sebesar " &
karyawanItem.Penghasilan.ToString("C") _
& vbCrLf & vbCrLf
' memakai referensi yang menunjuk ke
sebuah CKaryawanPerJam
karyawan = karyawanPerJam
keluaran &= GetString(karyawan)
& _
karyawanPerJam.ToString() &
" bergaji sebesar "
& _
karyawanPerJam.Penghasilan.ToString("C")
& vbCrLf & vbCrLf
MessageBox.Show(keluaran, "Demonstrasi Polimorfisme", _
MessageBoxButtons.OK,
MessageBoxIcon.Information)
End
Sub ' Main
' menghasilkan String yang memuat
informasi karyawan
Shared
Function GetString(ByVal
pekerja As CKaryawan) As String
Return
pekerja.ToString() & " bergaji
sebesar " & _
pekerja.Penghasilan.ToString("C") & vbCrLf
End
Function ' GetString
End Class '
CUji
|
Gambar 9.3 Keluaran
program pada kode 9.14
Baris 12 menugaskan sebuah objek CBoss kepada referensi CBoss, boss, dan melewatkan kepada konstruktornya nama pertama boss (“Djumanggal”), nama akhir (“Sianipar”), dan gaji mingguan (800). Baris 26 menugaskan referensi
kelas terderivasi, boss, kepada referensi
kelas basis CKaryawan, karyawan, sehingga dapat
didemonstrasikan kemampuan polimorfik atas penghasilan boss. Baris 27 melewatkan referensi karyawan sebagai argumen kepada
metode Private GetString (baris
53-56), yang secara polimorfik memanggil metode ToString dan Penghasilan
pada objek CKaryawan. Pada titik
ini, Visual Basic menentukan bahwa objek yang dilewatkan kepada GetString adalah bertipe CBoss, sehingga baris 54-55 memanggil
metode CBoss, ToString dan Penghasilan.
Metode Penghasilan menghasilkan sebuah objek Decimal. Kemudian, pada objek tersebut, metode ToString dipanggil. Pada kasus ini, string “C”, yang dilewatkan kepada versi teroverload dari metode ToString, merupakan kepanjangan dari Currency.
Ketika metode GetString kembali ke Main,
baris 27-28 secara eksplisit memanggil metode ToString dan Penghasilan
melalui referensi CBoss, boss, untuk menunjukkan bahwa
pemanggilan metode tersebut tidak menggunakan pemrosesan polimorfik. Keluaran
yang dihasilkan pada baris 27-28 identik dengan yang dihasilkan metode ToString dan Penghasilan melalui referensi kelas basis, karyawan.
Studi
Kasus: Menciptakan dan Menggunakan Antarmuka
Sekarang akan disajikan dua lagi contoh
polimorfisme melalui penggunaan antarmuka, yang menspesifikasi himpunan layanan
Public (metode dan properti) yang
harus diimplementasikan oleh kelas. Antarmuka digunakan ketika tidak ada
implementasi default yang akan diwarisi (tidak ada variabel instans dan tidak
ada implementasi metode default). Sedangkan kelas abstrak paling baik digunakan
untuk menyediakan data dan layanan untuk objek-objek di dalam relasi hirarki
pewarisan.
Definisi antarmuka dimulai dengan katakunci
Interface dan memuat sejumlah metode
dan properti Public. Untuk
menggunakan antarmuka, sebuah kelas harus menspesifikasi bahwa ia
mengimplementasikan (Implements)
antarmuka dan harus menyediakan implementasi atas tiap metode dan properti yang
dispesifikasi di dalam definisi antarmuka. Memiliki sebuah kelas yang
mengimplementasikan antarmuka adalah seperti menandatangani kontrak dengan
kompiler yang menyatakan bahwa “kelas ini akan mendefinisikan semua metode dan
properti yang dispesifikasi oleh antarmuka”.
Pada contoh ini, akan digunakan
antarmuka IUsia (kode 9.15) untuk
menghasilkan informasi usia bagi kelas COrang
(kode 9.16) dan CPohon (kode 9.17).
Definisi antarmuka IUsia diawali
pada baris 4 dengan Public Interface
dan berakhir pada baris 10 dengan End
Interface. Baris 7-8 menspesifikasi properti Usia dan Nama, dimana
setiap kelas yang mengimplementasikan antarmuka IUsia harus menyediakan implementasi atas kedua properti tersebut.
Antarmuka IUsia mendeklarasikan
kedua properti itu sebagai ReadOnly.
1
2
3
4
5
6
7
8
9
10
|
' Kode 9.15: IUsia.vb
' Antarmuka
IUsia mendeklarasikan properti untuk menetapkan dan mendapatkan usia.
Public Interface IUsia
' kelas yang mengimplementasikan IUsia harus
mendefinisikan kedua properti ini
ReadOnly Property Usia() As
Integer
ReadOnly Property Nama() As
String
End Interface ' IUsia
|
Baris 5 pada kode 9.16 menggunakan
katakunci Implements untuk
mengindikasikan bahwa kelas COrang
mengimplementasikan antarmuka IUsia.
Pada contoh ini, kelas COrang hanya
mengimplementasikan satu antarmuka. Sebuah kelas dapat mengimplementasikan
sebanyak mungkin antarmuka. Untuk mengimplementasikan lebih dari satu
antarmuka, definisi kelas harus menyediakan daftar antarmuka, yang dipisahkan
oleh koma, setelah katakunci Implements.
Kelas COrang memiliki variabel
anggota mTahunLahir, mNamaPertama, dan mNamaAkhir (baris 7-9), yang diinisialisasi oleh konstruktor pada
baris 12-29. Karena kelas COrang
mengimplementasikan antarmuka IUsia,
kelas COrang harus mengimplementasikan properti Usia dan Nama, yang didefinisikan pada baris 32-39 dan baris 42-49. Properti
Usia membolehkan klien untuk
mendapatkan usia seseorang dan properti Nama
menghasilkan sebuah String yang
memuat NamaPertama dan NamaAkhir. Perhatikan bahwa properti Usia menghitung usia seseorang dengan
mengurangkan mTahunLahir dari tahun
sekarang (via properti Tahun dari
properti Date.Now, yang menghasilkan
tanggal sekarang).
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
|
' Kode 9.16: Orang.vb
' Kelas COrang memiliki
hari lahir.
Public Class
COrang
Implements
IUsia
Private
mTahunLahir As Integer
Private
mNamaPertama As String
Private
mNamaAkhir As String
' konstruktor menerima nama pertama, nama
akhir, dan tanggal lahir
Public
Sub New(ByVal nilaiNamaPertama
As String, _
ByVal
nilaiNamaAkhir As String, _
ByVal
nilaiTahunLahir As Integer)
' pemanggilan implisit terhadap
konstruktor Object
mNamaPertama = nilaiNamaPertama
mNamaAkhir = nilaiNamaAkhir
' validasi tahun
If
(nilaiTahunLahir > 0 AndAlso _
nilaiTahunLahir <= Date.Now.Year) Then
mTahunLahir = nilaiTahunLahir
Else
mTahunLahir = Date.Now.Year
End
If
End
Sub ' New
' implementasi atas properti Usia dari
antarmuka IUsia
ReadOnly
Property Usia() As Integer _
Implements
IUsia.Usia
Get
Return Date.Now.Year - mTahunLahir
End
Get
End
Property ' Usia
' implementasi properti Nama dari
antarmuka IUsia
ReadOnly
Property Nama() As String _
Implements
IUsia.Nama
Get
Return mNamaPertama & " " & mNamaAkhir
End Get
End
Property ' Nama
End Class '
COrang
|
Kelas CPohon (kode 9.17) juga mengimplementasikan antarmuka IUsia. Kelas CPohon memiliki variabel anggota mLingkar (baris 7), yang merepresentasikan jumlah lingkar pada
batang pohon, dimana variabel ini berkaitan secara langsung dengan usia pohon.
Konstruktor CPohon (baris 10-14)
menerima sebagai argumen sebuah Integer
yang menspesifikasi kapan pohon ditanam. Kelas CPohon mencakup metode TambahLingkar
(baris 17-19), yang memampukan pengguna dalam menginkremen jumlah lingkar pada
pohon. Karena kelas CPohon
mengimplementasikan antarmuka IUsia,
kelas CPohon harus
mengimplementasikan properti Usia
dan Nama, yang didefinisikan pada
baris 22-29 dan baris 32-39. Properti Usia
menghasilkan nilai dari mLingkar,
dan properti Nama menghasilkan String “Pohon”.
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
|
' Kode 9.17: Pohon.vb
' Kelas CPohon memuat jumlah lingkar terkait dengan usia pohon.
Public Class CPohon
Implements IUsia
Private mLingkar As
Integer
' konstruktor menerima tanggal
penanaman pohon
Public Sub New(ByVal
tahunDitanam As Integer)
' pemanggilan implisit
terhadap konstruktor Object
mLingkar = Date.Now.Year - tahunDitanam
End Sub ' New
' menginkremen mLingkar
Public Sub TambahLingkar()
mLingkar += 1
End Sub ' TambahLingkar
' properti Usia
ReadOnly Property Usia() As
Integer _
Implements
IUsia.Usia
Get
Return mLingkar
End Get
End Property ' Usia
' implementasi properti Nama
dari antarmuka IUsia
ReadOnly Property Nama() As
String _
Implements IUsia.Nama
Get
Return "Pohon"
End Get
End Property ' Nama
End Class ' CPohon
|
Kelas CUji (kode 9.18) mendemonstrasikan polimorfisme pada beberapa objek
dari kelas COrang dan CPohon. Baris 11 menginstansiasi objek pohon dari kelas CPohon, dan baris 12 menginstansiasi objek orang dari kelas COrang. Baris 15 mendeklarasikan iArrayUsia, sebuah array yang memuat
dua referensi yang menunjuk ke objek IUsia.
Baris 18 dan 21 menugaskan pohon dan
orang kepada referensi pertama dan
referensi kedua di dalam iArrayUsia.
Baris 24-26 memanggil metode ToString
pada pohon, kemudian memanggil
propertinya, Usia dan Nama, untuk menghasilkan informasi usia
dan nama untuk objek pohon. Baris
29-31 memanggil metode ToString pada
orang, kemudian memanggil propertinya,
Usia dan Nama, untuk menghasilkan informasi usia dan nama untuk objek orang. Selanjutnya, kedua objek
tersebut akan dimanipulasi secara polimorfik melalui iArrayUsia, yang memuat referensi yang menunjuk ke objek IUsia. Baris 36-39 mendefinisikan sebuah
struktur For-Each yang menggunakan
properti Usia dan Nama untuk mendapatkan informasi usia
dan nama bagi tiap objek IUsia di
dalam iArrayUsia. Perhatikan bahwa Nama digunakan sehingga setiap objek di
dalam iArrayUsia dapat
“mengidentifikasi” dirinya di dalam keluaran program. Objek pohon dan orang dapat menggunakan metode ToString
untuk melakukan ini, karena kelas CPohon
dan COrang keduanya mewarisi kelas Object. Namun, ketika CUji berinteraksi dengan dua objek
tersebut secara polimorfik, CUji
hanya dapat menggunakan properti Usia
dan Nama untuk setiap objek
antarmuka. Karena antarmuka IUsia
tidak menyediakan metode ToString,
klien tidak dapat memanggil metode ToString
melalui referensi antarmuka IUsia.
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
|
' Kode 9.18: Uji.vb
' Demonstrasi polimorfisme.
Imports System.Windows.Forms
Class CUji
Shared Sub Main()
' instansiasi objek CPohon
dan COrang
Dim pohon As New
CPohon(1977)
Dim orang As New
COrang("Djumanggal",
"Sianipar", 1950)
' instansiasi array yang
memuat referensi kelas basis
Dim iArrayUsia(1) As
IUsia
' iArrayUsia(0)
mereferensi objek CPohon
iArrayUsia(0) = pohon
' iArrayUsia(1)
mereferensi objek COrang
iArrayUsia(1) = orang
' menampilkan informasi
pohon
Dim keluaran As String = pohon.ToString() & ": "
& _
pohon.Nama & vbCrLf
& "Usia pohon adalah
" & pohon.Usia & vbCrLf & _
vbCrLf
' menampilkan informasi
orang
keluaran &=
orang.ToString() & ": " & _
orang.Nama & vbCrLf
& "Usia orang adalah
" & orang.Usia & _
vbCrLf
Dim referensiUsia As
IUsia
' menampilkan nama dan
usia untuk tiap objek IUsia di dalam iArrayUsia
For Each referensiUsia In
iArrayUsia
keluaran &= vbCrLf
& referensiUsia.Nama & ": " & _
"Usia adalah " &
referensiUsia.Usia
Next
MessageBox.Show(keluaran,
"Demonstrasi Polimorfisme")
End Sub ' Main
End Class ' CUji
|
Gambar 9.4 Keluaran
program pada kode 9.18
Pada contoh selanjutnya akan diuji
kembali hirarki CTitik-CLingkaran-CSilinder menggunakan sebuah antarmuka, menggantikan penggunaan
kelas abstrak. Sekarang akan ditunjukkan bagaimana sebuah kelas dapat
mengimplementasikan antarmuka, kemudian berperan sebagai kelas basis untuk
kelas-kelas terderivasi untuk mewawariskan implementasi. Antarmuka IBangun (kode 9.19) akan diciptakan,
yang menspesifikasi metode Luas dan Volume dan properti Nama (baris 7-9). Setiap kelas yang
mengimplementasikan antarmuka IBangun harus menyediakan implementasi atas kedua
implementasi dan properti.
Karena kelas CTitik3 (kode 9.20) mengimplementasikan antarmuka IBangun, kelas CTitik3 harus mengimplementasikan ketiga anggota IBangun. Baris 55-59
mengimplementasikan metode Luas,
yang menghasilkan 0, karena titik memiliki luas nol. Baris 62-66
mengimplementasikan metode Volume,
yang juga menghasilkan 0, karena titik memiliki volume nol. Baris 69-76
mengimplementasikan properti ReadOnly,
Nama, yang menghasilkan nama kelas
sebagai sebuah String (“CTitik3”). Perhatikan bahwa penyertaan
katakunci Implements diikuti dengan
nama metode/properti antarmuka di dalam implementasi metode/properti. Katakunci
tersebut menginformasikan kompiler bahwa setiap metode/properti adalah
implementasi dari metode/properti antarmuka terkait. Juga perhatikan bahwa
kelas CTitik3 menspesifikasi
metode/properti sebagai Overridable,
yang memampukan kelas terderivasi mendefinisikan-ulang metode/properti
tersebut.
Ketika sebuah kelas mengimplementasikan
antarmuka, kelas memiliki relasi “adalah suatu” seperti yang dimiliki
pewarisan. Pada contoh ini, kelas CTitik3
mengimplementasikan antarmuka IBangun.
Oleh karena itu, objek CTitik3 adalah suatu IBangun, dan objek-objek dari sembarang kelas yang mewarisi CTitik3 adalah juga objek IBangun. Sebagai contoh, kelas CLingkaran3 (kode 9.21) mewarisi kelas CTitik3; jadi, sebuah CLingkaran3 adalah suatu IBangun.
Kelas CLingkaran3
mengimplementasikan antarmuka IBangun
secara implisit, karena kelas CLingkaran3
mewarisi metode-metode IBangun yang
diimplementasikan oleh CTitik.
Karena lingkaran tidak memiliki volume, kelas CLingkaran3 mewarisi metode Volume
dari kelas CTitik3, yang
menghasilkan nol. Namun, Anda tentu tidak ingin menggunakan metode Luas atau properti Nama dari kelas CTitik3
untuk kelas CLingkaran3. Kelas CLingkaran3 harus menyediakan
implementasi sendiri untuk metode dan properti tersebut, karena luas dan nama
sebuah lingkaran berbeda dari sebuah titik. Baris 51-53 mendefinisikan-ulang
metode Luas untuk menghasilkan luas
lingkaran, dan baris 56-62 mendefinisikan-ulang properti Nama untuk menghasilkan String”CLingkaran3”.
Kelas CSilinder3 (kode 9.22) mewarisi kelas CLingkaran3. Kelas CSilinder3
mengimplementasikan antarmuka IBangun
secara implisit, karena kelas CSilinder3
mewarisi Luas dan properti Nama dari kelas CLingkaran3 dan metode Volume
dari kelas CTitik3. Namun, kelas CSilinder3 mendefinisikan-ulang
properti Nama dan metode Luas dan Volume untuk melakukan operasi-operasi yang spesifik untuk CSilinder3. Baris 43-45
mendefinisikan-ulang metode Luas
untuk menghasilkan luas permukaan silinder, baris 48-50 mendefinisikan-ulang
metode Volume untuk menghasilkan
volume silinder dan baris 58-64 mendefinisikan-ulang properti Nama untuk menghasilkan String “CSilinder3”.
1
2
3
4
5
6
7
8
9
10
11
|
' Kode 9.19: Bangun.vb
' Antarmuka IBangun untuk hirarki Titik, Lingkaran, dan Silinder.
Public Interface IBangun
' kelas-kelas yang
mengimplementasikan IBangun harus mendefinisikan metode/properti ini
Function Luas() As Double
Function Volume() As
Double
ReadOnly Property
Nama() As String
End Interface ' IBangun
|
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
|
' Kode 9.20: Titik3.vb
' kelas CTitik3
mengimplementasikan IBangun.
Public Class
CTitik3
Implements
IBangun ' CTitik3 mewarisi antarmuka IBangun
' koordinat titik
Private
mX, mY As Integer
' konstruktor default
Public
Sub New()
X = 0
Y = 0
End
Sub ' New
' konstruktor
Public
Sub New(ByVal xNilai As Integer, _
ByVal
yNilai As Integer)
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
CTitik3
Public
Overrides Function ToString() As
String
Return
"[" & mX & ", " & mY & "]"
End
Function ' ToString
' implementasi metode Luas antarmuka
IBangun
Public
Overridable Function Luas() As
Double _
Implements
IBangun.Luas
Return
0
End
Function ' Luas
' implementasi metode Volume antarmuka
IBangun
Public
Overridable Function Volume() As
Double _
Implements
IBangun.Volume
Return
0
End
Function ' Volume
' implementasi properti Nama antarmuka
IBangun
Public
Overridable ReadOnly Property Nama() As
String _
Implements
IBangun.Nama
Get
Return "CTitik3"
End
Get
End
Property ' Nama
End Class '
CTitik3
|
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
|
' Kode 9.21: Lingkaran3.vb
' Kelas CLingkaran3 mewarisi
kelas CTitik3 dan mendefinisikan-ulang beberapa metodenya
Public Class
CLingkaran3
Inherits
CTitik3 ' CLingkaran3 mewarisi kelas CTitik3
Private
mRadius As Double ' radius
CLingkaran3
' konstruktor default
Public
Sub New()
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 CTitik3 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 ' mRadius tidak bisa bernilai nagatif
End If
End
Set
End
Property ' Radius
' menghitung diameter CLingkaran3
Public
Function Diameter() As Double
Return
mRadius * 2
End
Function ' Diameter
' menghitung keliling CLingkaran3
Public
Function Keliling() As Double
Return
Math.PI * Diameter()
End
Function ' Keliling
' menghitung luas CLingkaran3
Public
Overrides Function Luas() As
Double
Return
Math.PI * mRadius ^ 2
End
Function ' Luas
' mendefinisikan-ulang properti Nama
antarmuka IBangun dari kelas CTitik3
Public
Overrides ReadOnly Property Nama() As
String
Get
Return "CLingkaran3"
End
Get
End
Property ' Nama
' menghasilkan representasi String atas
CLingkaran3
Public
Overrides Function ToString() As
String
' menggunakan referensi MyBase untuk menghasilkan
representasi String CLingkaran3
Return
"Pusat= " &
MyBase.ToString() & _
"; Radius = " & mRadius
End
Function ' ToString
End Class '
CLingkaran3
|
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
|
' Kode 9.22: Silinder3.vb
' Kelas CSilinder3 mewarisi
kelas CLingkaran3 dan mendefinisikan-ulang beberapa anggota.
Public Class
CSilinder3
Inherits
CLingkaran3 ' CSilinder3 mewarisi
kelas CLingkaran3
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 CLingkaran3
MyBase.New(xNilai, yNilai, nilaiRadius)
Tinggi = nilaiTinggi ' menetapkan
tinggi CSilinder2
End
Sub ' New
' properti Tinggi
Public
Property Tinggi() As Double
Get
Return mTinggi
End
Get
' menetapkan tinggi CSilinder3 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 CSilinder3
Public
Overrides Function Luas() As
Double
Return
2 * MyBase.Luas + MyBase.Keliling
* mTinggi
End
Function ' Luas
' menghitung volume CSilinder3
Public
Overrides Function Volume() As
Double
Return
MyBase.Luas * mTinggi
End
Function ' Volume
' mengkonversi CSilinder3 menjadi String
Public
Overrides Function ToString() As
String
Return
MyBase.ToString() & "; Tinggi = " & mTinggi
End
Function ' ToString
' mendefinisikan-ulang properti Nama dari
kelas CLingkaran3
Public
Overrides ReadOnly Property Nama() As
String
Get
Return "CSilinder3"
End
Get
End
Property ' Nama
End Class '
CSilinder3
|
Kelas CUji3 (kode 9.23) mendemonstrasikan hirarki
titik-lingkaran-silinder yang menggunakan antarmuka. Kelas CUji3 hanya memiliki dua perbedaan dari kode 9.8, yang menguji
hirarki kelas yang diciptakan dari kelas basis MustInherit, CBangun. Pada kode 9.23, baris 16 mendeklarasikan
arrayBangun sebagai sebuah array
yang memuat beberapa referensi antarmuka IBangun.
Pada kode 9.8, beberapa pemanggilan terhadap metode ToString dilakukan melalui referensi kelas basis CBangun, tetapi, karena antarmuka IBangun tidak menyediakan metode ToString, klien tidak dapat memanggil
metode ToString pada tiap objek IBangun.
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
|
' Kode 9.23: Uji3.vb
' Demonstrasi polimorfisme dalam hirarki Titik-Lingkaran-Silinder.
Imports System.Windows.Forms
Class CUji3
Shared Sub Main()
' instansiasi objek
CTitik3, CLingkaran3, dan CSilinder3
Dim titik As New
CTitik3(7, 11)
Dim lingkaran As New
CLingkaran3(22, 8, 3.5)
Dim silinder As New
CSilinder3(10, 10, 3.3, 10)
' instansiasi array yang
memuat beberapa referensi kelas basis
Dim arrayBangun(2) As
IBangun
' arrayBangun(0)
mereferensi objek CTitik3
arrayBangun(0) = titik
' arrayBangun(1)
mereferensi objek CLingkaran3
arrayBangun(1) = lingkaran
' arrayBangun(2)
mereferensi objek CSilinder3
arrayBangun(2) = silinder
Dim keluaran As String = titik.Nama & ":
" & _
titik.ToString() &
vbCrLf & lingkaran.Nama & ": " & _
lingkaran.ToString() &
vbCrLf & silinder.Nama & _
": " &
silinder.ToString()
Dim bangun As IBangun
' menampilkan nama, luas,
dan volume untuk tiap objek di
' dalam arrayBangun
For Each bangun In
arrayBangun
keluaran &= vbCrLf
& vbCrLf & bangun.Nama & ": " & _
vbCrLf & "Luas = " & _
String.Format("{0:F}", bangun.Luas) & vbCrLf &
_
"Volume = " &
String.Format("{0:F}", bangun.Volume)
Next
MessageBox.Show(keluaran,
"Demonstrasi Polimorfisme")
End Sub ' Main
End Class ' CUji3
|
Gambar 9.5 Keluaran
program pada kode 9.23
Delegate
Pada Bab 5, telah didiskusikan
bagaimana objek dapat melewatkan variabel anggota sebagai argumen kepada
metode. Namun, kadangkala, lebih menguntungkan bagi objek untuk melewatkan
metode sebagai argumen kepada metode lainnya. Sebagai contoh, misalnya Anda
ingin mengurutkan sederet nilai dalam urutan menaik dan urutan menurun.
Daripada harus menyediakan dua metode terpisah untuk mengurutkan menaik dan
mengurutkan menurun, Anda dapat menggunakan satu metode yang menerima sebagai
argumen sebuah referensi yang menunjuk ke metode perbandingan yang digunakan.
Untuk melakukan pengurutan menaik, Anda dapat melewatkan referensi metode
pengurut kepada metode perbandingan-pengurutan-menaik; Untuk melakukan pengurutan menurun, Anda
dapat melewatkan referensi metode pengurut kepada metode perbandingan-pengurutan-menurun.
Metode pengurut kemudian akan menggunakan referensi ini untuk mengurutkan
sederet nilai.
Visual Basic tidak mengijinkan
pelewatan referensi metode secara langsung sebagai argumen kepada metode lain,
tetapi menyediakan delegate, yang merupakan kelas yang mengenkapsulasi himpunan
referensi yang menunjuk ke metode. Sebuah objek delegate yang memuat
referensi-referensi metode dapat dilewatkan kepada metode lain. Daripada
mengirimkan referensi metode secara langsung, sebuah objek dapat mengirimkan instans
delegate, yang memuat referensi metode. Metode yang menerima referensi, yang
menunjuk ke delegate, kemudian dapat memanggil metode yang dimuat di dalam
delegate.
Delegate yang memuat satu metode
dikenal dengan delegate singlecast dan diciptakan atau diderivasi dari kelas Delegate. Delegate yang memuat banyak
metode dikenal dengan delegate multicast dan diciptakan atau diderivasi dari
kelas MulticastDelegate. Kedua jenia
delegate berada di dalam namespace System.
Untuk menggunakan delegate, Anda harus
mendeklarasikannya lebih dahulu. Deklarasi delagate menspesifikasi sidik metode
(parameter dan nilai balik). Metode, dengan referensi yang akan dimuat di dalam
objek delegate, harus memiliki sidik metode yang sama dengan yang didefinisikan
di dalam deklarasi delagate. Anda kemudian menciptakan metode yang memiliki
sidik ini. Langkah ketiga adalah menciptakan instans delegate via katakunci AddressOf. Setelah instans delegate
diciptakan, Anda dapat memanggil referensi metode yang dimuatnya. Proses ini
akan ditunjukkan pada contoh berikutnya.
Kelas CUrutBubbleDelegate (kode 9.24), yang dimodifikasi dari contoh
pengurutan-bubble pada Bab 6, menggunakan beberapa delaget untuk mengurutkan
sebuah array Integer dengan urutan
menaik atau urutan menurun. Baris 7-9 menyediakan deklarasi untuk delegate Komparator. Untuk mendeklarasikan
sebuah delegate (baris 7), Anda mendeklarasikan sidik suatu metode, dimana
katakunci Delegate ditempatkan
setelah pemodifikasi akses-anggota (pada kasus ini, Public), diikuti dengan katakunci Function (atau katakunci Sub),
nama delegate, daftar parameter, dan tipe nilai balik. Delegate Komparator mendefinisikan suatu sidik
metode untuk metode yang menerima dua argumen Integer dan yang menghasilkan nilai balik Boolean. Perhatikan bahwa delegate Komparator tidak memiliki tubuh. Seperti yang akan
didemonstrasikan, aplikasi ini (kode 9.25) mengimplementasikan metode yang
sesuai dengan sidik delegate Komparator,
kemudian melewatkan metode tersebut (sebagai argumen bertipe Komparator) kepada metode UrutArray. Perhatikan bahwa Anda
mendeklarasikan delegate Komparator
sebagai sebuah Function, karena ia
menghasilkan nilai balik (bertipe Boolean).
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 9.24: UrutBubbleDelegate.vb
' Uses delegates to sort random numbers (ascending or descending).
Public Class CUrutBubbleDelegate
' definisi delegate
Public Delegate Function Komparator( _
ByVal
elemen1 As Integer, _
ByVal
elemen2 As Integer) As Boolean
' mengurutkan array tergantung
dari komparator
Public Sub UrutArray(ByVal
array() As Integer, _
ByVal
Banding As Komparator)
Dim i, pass As Integer
For pass = 0 To
array.Length - 1
' perbandingan loop
sebelah dalam
For i = 0 To
array.Length - 2
If Banding(array(i), array(i + 1)) Then
Tukar(array(i), array(i + 1))
End If
Next ' loop sebelah dalam
Next ' loop sebelah luar
End Sub ' UrutArray
' menukar dua elemen
Private Sub Tukar(ByRef
elemenPertama As Integer, _
ByRef
elemenKedua As Integer)
Dim tampung As Integer
tampung = elemenPertama
elemenPertama =
elemenKedua
elemenKedua = tampung
End Sub ' Tukar
End Class ' CUrutBubbleDelegate
|
Baris 12-30 mendefinisikan metode UrutArray, yang mengambil sebuah
argumen dan sebuah referensi yang menunjuk ke Komparator sebagai argumen. Metode UrutArray memodifikasi array dengan mengurutkan isinya. Baris 22
menggunakan metode delegate dalam menentukan bagaimana mengurutkan array. Baris
22 memanggil metode yang diapit di dalam objek delegate dengan memperlakukan
referensi delegate sebagai metode yang dimuat objek delegate. Visual Basic
memanggil referensi metode yang diapit secara langsung, melewatkan padanya
parameter array(i) dan array(i+1). Komparator menentukan tipe pengurutan untuk kedua argumennya. Untuk
mengurutkan secara menaik, Komparator
akan menghasilkan True ketika elemen
pertama yang sedang dibandingkan lebih besar dari elemen kedua. Sama halnya,
untuk mengurutkan secara menurun, Komparator
menghasilkan True ketika elemen
pertama yang sedang dibandingkan lebih kecil dari elemen kedua.
Kelas CFrmUrutBubble (kode 9.25) menampilkan sebuah Form dengan dua kotak teks dan tiga tombol. Kotak teks pertama
menampilkan sederet angka tak-terurut, dan kotak teks kedua menampilkan sederet
angka yang telah diurutkan. Tombol Ciptakan
Data menciptakan sederet nilai yang tak-terurut. Tombol Urutkan Menaik dan Urutkan Menurun mengurutkan array dengan urutan menaik dan menurun.
Metode UrutMenaik (baris 31-35) dan UrutMenurun (baris 38-42) masing-masing
memiliki sebuah sidik yang berkaitan dengan sidik yang didefinisikan oleh
deklarasi delegate Komparator
(yaitu, masing-masing menerima dua Integer
dan menghasilkan nilai balik Boolean).
Seperti yang Anda akan lihat, program melewatkan kepada CUrutBubble-Delegate dua delegate UrutArray yang memuat dua referensi yang menunjuk ke UrutMenaik dan UrutMenurun, yang akan menentukan watak pengurutan CUrutBubbleDelegate.
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
|
' Kode 9.25:
FrmUrutBubble.vb
' Menciptakan GUI yang
memampukan pengguna dalam mengurutkan array.
Imports
System.Windows.Forms
Public Class
CFrmUrutBubble
Inherits
Form
' TextBox yang memuat sederet nilai awal
Friend
WithEvents txtAsli As TextBox
Friend
WithEvents lblAsli As Label
' TextBox yang memuat sederet nilai yang
telah terurut
Friend
WithEvents txtTerurut As
TextBox
Friend
WithEvents lblTerurut As Label
' Button untuk menciptakan dan
mengurutkan sederet nilai
Friend
WithEvents cmdCiptakan As
Button
Friend
WithEvents cmdUrutkanMenaik As
Button
Friend
WithEvents cmdUrutkanMenurun As
Button
' kode yang dibangkitkan oleh Windows
Form Designer
' referensi yang menunjuk ke objek yang
memuat delegate
Dim
mUrutBubble As New
CUrutBubbleDelegate()
' array asli dengan elemen-elemen
tak-terurut
Dim
mElemenArray(9) As Integer
' implementasi delegate pengurutan
secaran menaik
Private
Function UrutMenaik(ByVal
elemen1 As Integer, _
ByVal
elemen2 As Integer) As Boolean
Return
elemen1 > elemen2
End
Function ' UrutMenaik
' implementasi delegate pengurutan secara
menurun
Private
Function UrutMenurun(ByVal
elemen1 As Integer, _
ByVal
elemen2 As Integer) As Boolean
Return
elemen1 < elemen2
End
Function ' UrutMenurun
' menciptakan sederet nilai secara acak
Private
Sub cmdCiptakan_Click(ByVal
sender As System.Object, _
ByVal
e As System.EventArgs) Handles cmdCiptakan.Click
txtTerurut.Clear()
Dim
keluaran As String
Dim
angkaAcak As Random = New Random()
Dim
i As Integer
' menciptakan String dengan 10 angka
acak
For
i = 0 To mElemenArray.Length - 1
mElemenArray(i) = angkaAcak.Next(100)
keluaran &= mElemenArray(i)
& vbCrLf
Next
txtAsli.Text = keluaran ' menampilkan
angka-angka
' mengaktifkan tombol pengurutan
cmdUrutkanMenaik.Enabled = True
cmdUrutkanMenurun.Enabled = True
End
Sub ' cmdCiptakan_Click
' menampilkan isi array di dalam TextBox
tertentu
Private
Sub TampilHasil()
Dim
keluaran As String
Dim
i As Integer
' menciptakan string dengan sederet
angka terurut
For
i = 0 To mElemenArray.Length - 1
keluaran &= mElemenArray(i)
& vbCrLf
Next
txtTerurut.Text = keluaran '
menampilkan angka-angka
End
Sub ' TampilHasil
'
mengurutkan sederet nilai secara menaik
Private
Sub cmdUrutkanMenaik_Click(ByVal
sender As _
System.Object, ByVal e As
System.EventArgs) _
Handles
cmdUrutkanMenaik.Click
' mengurutkan array
mUrutBubble.UrutArray(mElemenArray,
AddressOf UrutMenaik)
TampilHasil() ' menampilkan hasil
cmdUrutkanMenaik.Enabled = False
cmdUrutkanMenurun.Enabled = True
End
Sub ' cmdUrutkanMenaik_Click
' mengurutkan sederet nilai secara
menurun
Private
Sub cmdUrutkanMenurun_Click(ByVal
sender As _
System.Object, ByVal e As
System.EventArgs) _
Handles
cmdUrutkanMenurun.Click
' mengurutkan objek dan mengurutkan
array
mUrutBubble.UrutArray(mElemenArray,
AddressOf UrutMenurun)
TampilHasil() ' menampilkan hasil
cmdUrutkanMenaik.Enabled = False
cmdUrutkanMenurun.Enabled = True
End
Sub ' cmdUrutkanMenurun_Click
End Class ' CFrmUrutBubble
|
Gambar 9.6 Keluaran
program pada kode 9.25
Latihan
1.
Modifikasilah sistem penggajian pada kode 9.10 –
9.14 dan tambahkan dua variabel instans Private,
yaitu mTanggalLahir (menggunakan
kelas CHari dari kode 7.8) dan mKode-Departemen (sebuah Integer) kepada kelas CKaryawan. Asumsikan bahwa penggajian
diproses sekali dalam sebulan. Ciptakan sebuah array yang memuat beberapa
referensi CKaryawan untuk menyimpan
pelbagai objek karyawan. Menggunakan sebuah loop, hitung penggajian untuk tiap CKaryawan (secara polimorfik).
2.
Implementasikan hirarki CBangun yang ditampilkan pada Gambar 8.3. Setiap CBangun-DuaDimensi harus memuat metode Luas untuk menghitung luas bangun dua
dimensi. Setiap CBangunTigaDimensi
harus memuat metode Luas dan Volume untuk menghitung luas permukaan dan
volume bangun tiga dimensi. Ciptakan program yang menggunakan sebuah array yang
memuat beberapa referensi CBangun
yang menunjuk ke setiap kelas konkrit di dalam hirarki. Program harus
menampikan representasi String untuk
tiap objek di dalam array. Di samping itu, di dalam loop yang memproses semua
bangun di dalam array, tentukan apakah suatu bangun adalah sebuah CBangunDuaDimensi atau sebuah CBangunTigaDimensi. Jika suatu bangun
adalah CBangunDuaDimensi, maka
tampilkan Luasnya. Jika suatu bangun
adalah CBangunTigaDimensi, maka
tampilkan Luas dan Volumenya.
No comments:
Post a Comment