Saturday, December 24, 2016

Bab 8. Visual Basic .NET Belajar Dari Contoh



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