Bab.
10 Lebih Lanjut Dengan Objek
10.1 Introduksi
Pada dua bab sebelumnya, Anda
telah belajar tentang objek dan kelas. Anda telah belajar bagaimana
mendefinisikan kelas, menciptakan objek, dan menggunakan objek dari beberapa
kelas dalam JAVA API (misalnya, Date,
Random, String, StringBuilder, File, Scanner, dan PrintWriter).
Bab ini dikhususkan untuk mengenalkan teknik pemrograman fundamental dan
penyelesaian masalah dalam pemrograman berorientasi-objek. Bab ini akan
menunjukkan bagaimana pemrograman prosedural dan pemrograman berorientasi-objek
berbeda.
Fokus di sini adalah merancang
kelas. Akan disajikan beberapa contoh untuk mengilustrasikan keuntungan
pendekatan berorientasi-objek. Beberapa contoh yang diberikan melibatkan
kelas-kelas baru dan menerapkannya dalam aplikasi.
10.2 Objek dan Kelas Immutable
Normalnya, Anda menciptakan suatu
objek dan mengijinkan isinya untuk diubah pada waktu yang akan datang. Tetapi,
dalam beberapa kesempatan, Anda menginginkan suatu objek yang memiliki yang
tidak dapat diubah. Objek semacam itu disebut dengan objek immutable dan kelasnya dikatakan dengan kelas immutable. Kelas String,
misalnya, adalah immutable. Jika Anda
menghapus metode tetapkanRadius()
dalam kelas Lingkaran2 pada kode8.9,
maka kelas tersebut akan menjadi immutable,
karena radius dideklarasikan private dan tidak bisa diubah tanpa
bantuan metode tetapkanRadius().
Jika suatu kelas immutable, maka semua bidang data harus
privat dan tidak bisa memuat metode publik semacam tetapkanRadius() untuk mengubah bidang data. Metode publik yang
mengubah bidang data privat disebut juga dengan mutator. Suatu kelas dengan
semua bidang data privat tanpa mutator belum tentu immutable. Sebagai contoh, kelas Siswa memiliki semua bidang data privat dan tanpa mutator, tetapi
bukan merupakan kelas immutable.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class Siswa {
private int id;
private String nama;
private java.util.Date
tanggalDiciptakan;
public
Siswa(int ssn, String namaBaru) {
id = ssn;
nama = namaBaru;
tanggalDiciptakan
= new java.util.Date();
}
public
int dapatId() {
return id;
}
public
String dapatNama() {
return nama;
}
public java.util.Date
dapatTanggalDiciptakan() {
return
tanggalDiciptakan;
}
}
|
Seperti ditunjukkan pada kode di
bawah ini, bidang data tanggalDiciptakan
dikembalikan menggunakan metode dapatTanggalDiciptakan().
Ini merupakan referensi ke suatu objek Date.
Melalui referensi ini, isi tanggalDiciptakan
dapat diubah:
public
class Test {
public static void main(String[] args) {
Siswa siswa = new Siswa(111223333,
"Meika");
java.util.Date tanggalDiciptakan =
siswa.dapatTanggalDiciptakan();
tanggalDiciptakan.setTime(200000);
// Sekarang bidang data tanggalDiciptakan berubah!
}
}
Agar suatu kelas menjadi immutable, maka harus memenuhi tiga
persyaratan berikut ini:
1. Semua
bidang data harus privat.
2. Tidak ada
metode mutator.
3.
Tidak ada aksesor yang
mengembalikan suatu referensi ke suatu bidang data yang immutable.
10.3 Skop Variabel
Variabel instans dan variabel
statik di dalam suatu kelas dikenal juga dengan variabel kelas atau bidang
data. Suatu variabel yang didefinisikan di dalam suatu metode disebut dengan
variabel lokal. Skop dari variabel suatu kelas adalah keseluruhan kelas, tanpa
memandang tempat dimana variabel itu dideklarasikan.
Gambar
10.1
Anggota-anggota kelas dapat dideklarasikan dengan sembarang urutan, dengan satu
pengecualian
Variabel dan metode kelas dapat
muncul dengan sembarang urutan, seperti yang ditunjukkan pada Gambar 10.1a.
Pengecualiannya adalah ketika suatu bidang data diinisialisasi berdasarkan
bidang data lain. Pada kasus tersebut, bidang data lain itu harus
dideklarasikan terlebih dahulu, seperti ditampilkan pada Gambar 10.1b. Untuk
alasan kejelasan dan konsistensi, buku ini mendeklarasikan bidang data di awal
setiap kelas.
Anda bisa mendeklarasikan suatu
variabel kelas hanya sekali, tetapi Anda bisa mendeklarasikan nama variabel
sama di dalam suatu metode berulang kali pada blok-blok yang berbeda.
Jika suatu variabel lokal memiliki
nama yang sama dengan suatu varibel kelas, maka variabel lokal berkuasa dan
variabel kelas tersembunyi. Sebagai contoh, program berikut ini, x didefinisikan sebagai suatu variabel
instans dan sebagai suatu variabel lokal di dalam metode.
public class Foo {
private
int x = 0;// Variabel instans
private
int y = 0;
public
Foo() {
}
public
void p() {
int
x = 1;// Variabel lokal
System.out.println("x
= " + x);
System.out.println("y
= " + y);
}
}
Apakah keluaran dari f.p(), dimana f adalah suatu instans dari Foo?
Keluaran f.p() adalah 1 untuk x dan 0 untuk y. Berikut adalah alasannya:
·
x
dideklarasikan sebagai suatu bidang data dengan nilai awal 0 di dalam kelas,
tetapi juga dideklarasikan di dalam metode p()
dengan nilai awal 1. x yang ada di
dalam metode p() lah yang
direferensi oleh statemen System.out.println.
·
y
dideklarasikan di luara metode p(),
tetapi tetap dapat diakses dari dalam metode tersebut.
10.4 Referensi this
Katakunci this merupakan nama referensi yang menunjuk kepada objek pemanggil
itu sendiri. Salah satu kegunaanya adalah untuk mereferensi bidang data yang
tersembunyi. Anda perlu mereferensi bidang data tersembunyi di dalam metode
untuk menetapkan nilai yang baru.
Gambar
10.2
Katakunci this menunjuk kepada objek
pemanggil yang memanggil metode
Suatu variabel statik tersembunyi
bisa diakses dengan menggunakan referensi NamaKelas.VariabelStatik.
Suatu variabel instans tersembunyi bisa diakses menggunakan katakunci this, seperti yang ditampilkan pada
Gambar 10.2a.
Katakunci this memberi cara untuk menunjuk kepada objek yang memanggil suatu
metode. Baris this.i = i berarti
“menugaskan nilai parameter i kepada
bidang data i pada objek pemanggil”.
Baris Foo.k = k berarti bahwa nilai
parameter k ditugaskan kepada bidang
data statik k, yang dipakai bersama
oleh semua objek kelas.
Kegunaan lainnya dari katakunci this adalah untuk memampukan suatu
konstruktor untuk memanggil konstruktor lainnya pada kelas yang sama. Sebagai
contoh, Anda bisa menulis-ulang kelas Lingkaran
sebagai berikut:
Baris this(1.0) dalam konstruktor kedua memanggil konstruktor pertama
dengan argumen bertipe double.
10.5 Enkapsulasi dan Abstraksi
Kelas
Abstraksi kelas merupakan pemisahan implementasi kelas dari penggunaan
suatu kelas. Pencipta suatu kelas menjelaskan kelas dan memberitahu pengguna
bagaimana cara menggunakannya. Koleksi metode dan bidang data yang dapat
diakses dari luar kelas, bersama dengan deskripsi tentang bagaimana
anggota-anggota kelas tersebut berperilaku disebut dengan kontrak kelas.
Seperti yang ditunjukkan pada Gambar 10.3, pengguna kelas tidak perlu tahu
bagaimana kelas diimplementasikan. Detil implementasi dienkapsulasi dan
disembunyikan dari pengguna. Hal ini dikenal dengan enkapsulasi kelas. Sebagai contoh, Anda bisa menciptakan suatu
objek Lingkaran dan mencari luas
suatu lingkaran tanpa perlu mengetahui bagaimana luas lingkaran dihitung.
Gambar
10.3
Abstraksi kelas memisahkan implementasi kelas dari penggunaan kelas
Abstraksi kelas dan enkapsulasi
kelas seperti dua sisi suatu koin. Banyak contoh kehidupan nyata yang
mengilustrasikan konsep abstraksi kelas. Misalnya adalah suatu komputer.
Komputer pribari Anda memiliki beberapa komponen, seperti CPU, memori, motherboard, kipas, dan lain-lain.
Setiap komponen bisa dipandang sebagai objek yang memiliki watak dan metode.
Agar komponen-komponen tersebut bisa beroperasi bersama, Anda hanya perlu tahu
bagaimana setiap komponen digunakan dan bagaimana setiap komponen berinteraksi
satu sama lain. Anda tidak perlu mengetahui bagaimana setiap komponen
beroperasi secara internal. Implementasi internal setiap komponen dienkapsulasi
dan disembunyikan dari Anda. Anda bisa merakit suatu komputer tanpa perlu
mengetahui bagaimana setiap komponennya diimplementasikan.
Analogi komputer pribadi tersebut
secara tepat menggambarkan pendekatan berorientasi objek. Setiap komponen
komputer dapat dipandang sebagai suatu objek kelas. Sebagai contoh, Anda
menginginkan suatu kelas yang memodelkan semua jenis kipas di dalam suatu
komputer, dengan watak-watak seperti ukuran dan kecepatan dan metode-metode
untuk memulai beroperasi dan berhenti. Suatu kipas spesifik dipandang sebagai
suatu instans kelas dengan nilai-nilai watak tertentu.
Gambar 10.4
Kelas Hutang memodelkan watak dan
metode kelas
Contoh lain adalah pinjaman. Suatu
pinjaman tertentu dapat dipandang sebagai objek suatu kelas Hutang. Suku bunga, jumlah pinjaman,
dan periode pinjaman adalah beberapa watak kelas Hutang, dan menghitung pembayaran bulanan dan total pembayaran
adalah dua metode kelas ini. Ketika Anda membeli sebuah mobil, suatu objek
Hutang diciptakan dengan menginstansiasi kelas yang memiliki watak sku bunga,
jumlah pinjaman, dan periode pinjaman. Anda kemudian dapat menggunakan
metode-metode yang dimiliki kelas tersebut untuk menghitung pembayaran bulanan
dan total pembayaran dari hutang Anda. Sebagai pengguna dari kelas Hutang, Anda tidak perlu mengetahui
bagaimana metode-metode ini diimplementasikan.
Kode2.8, HitungHutang.java, telah
menghadirkan suatu program untuk menghitung pembayaran pinjaman. Program
tersebut tidak dapat digunakan-kembali oleh program lain. Salah satu cara untuk
mengatasi masalah ini adalah dengan mendefinisikan metode-metode statik untuk
menghitung pembayaran bulanan dan total pembayaran. Tetapi cara ini memiliki
keterbatasan, misalnya, ketika Anda ingin menggunakan tanggal pada pinjaman
tertentu. Cara ideal untuk mengatasi hal ini adalah dengan menciptakan suatu
objek yang mengikat watak informasi pinjaman dengan tanggal secara bersama. Gambar
10.4 menunjukkan diagram kelas UML untuk kelas Hutang.
Diagram UML pada Gambar 10.4
berperan sebagai kontrak untuk kelas Hutang.
Pada buku ini, Anda akan memainkan kedua peran sebagai pengguna kelas maupun
sebagai pengembang kelas. Penggunda dapat memakai kelas tanpa mengetahui
bagaimana kelas diimplementasikan. Diasumsikan bahwa kelas Hutang telah tersedia, Anda bisa menulis suatu program uji yang
menggunakan kelas tersebut (kode10.1).
Kode10.1 UjiKelasHutang.java
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
|
import java.util.Scanner;
public class UjiKelasHutang {
/**
Metode utama */
public
static void main(String[] args) {
//
Menciptakan Scanner
Scanner
masukan = new Scanner(System.in);
//
Memasukkan suku bunga tahunan
System.out.print(
"Masukkan
suku bunga tahunan, misalnya, 8.25: ");
double
sukuBungaTahunan = masukan.nextDouble();
//
Masukkan jumlah tahun
System.out.print("Masukkan
jumlah tahun sebagai suatu integer: ");
int
jumlahTahun = masukan.nextInt();
//
Masukkan jumlah pinjaman
System.out.print("Masukkan
jumlah pinjaman, misalnya, 120000.95: ");
double
jumlahPinjaman = masukan.nextDouble();
//
Menciptakan suatu objek Hutang
Hutang
hutang =
new Hutang(sukuBungaTahunan,
jumlahTahun, jumlahPinjaman);
// Menampilkan
tanggal pinjaman, pembayaran bulanan, dan pembayaran total
System.out.printf("Hutang
dibuat pada %s\n" +
"Pembayaran
bulanan sebesar %.2f\nPembayaran total sebesar %.2f\n",
hutang.dapatTanggalPinjaman().toString(), hutang.dapatPembayaranBulanan(),
hutang.dapatPembayaranTotal());
}
}
|
Metode main membaca suku bunga,
periode pembayaran, dan jumlah pinjaman; menciptakan suatu objek Hutang; dan mendapatkan pembayaran
bulanan (baris 29) dan pembayaran total (baris 30) menggunakan metode-metode
instans dalam kelas Hutang.
Kelas Hutang dapat diimplementasikan pada kode10.2 sebagai berikut:
Kode10.2 Hutang.java
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
|
public class
Hutang {
private
double sukuBungaTahunan;
private
int jumlahTahun;
private
double jumlahPinjaman;
private
java.util.Date tanggalPinjaman;
/**
Konstruktor Default */
public
Hutang() {
this(2.5,
1, 1000);
}
/**
Menciptakan suatu objek Hutang dengan suku bunga tahunan,
jumlah
tahun, dan jumlah pinjaman tertentu
*/
public Hutang(double
sukuBungaTahunan, int jumlahTahun,
double jumlahPinjaman){
this.sukuBungaTahunan
= sukuBungaTahunan;
this.jumlahTahun
= jumlahTahun;
this.jumlahPinjaman
= jumlahPinjaman;
tanggalPinjaman
= new java.util.Date();
}
/**
Mengembalikan sukuBungaTahunan */
public
double dapatSukuBungaTahunan() {
return
sukuBungaTahunan;
}
/**
Menetapkan sukuBungaTahunan yang baru */
public
void tetapkanSukuBungaTahunan(double sukuBungaTahunan) {
this.sukuBungaTahunan
= sukuBungaTahunan;
}
/**
Mengembalikan jumlahTahun */
public
int dapatJumlahTahun() {
return
jumlahTahun;
}
/**
Menetapkan jumlahTahun yang baru */
public
void tetapkanJumlahTahun(int numberOfYears) {
this.jumlahTahun
= jumlahTahun;
}
/**
Mengembalikan jumlahPinjaman */
public
double dapatJumlahPinjaman() {
return
jumlahPinjaman;
}
/**
Menetapkan jumlahPinjaman yang baru*/
public
void tetapkanJumlahPinjaman(double loanAmount) {
this.jumlahPinjaman
= jumlahPinjaman;
}
/**
Menghitung pembayaran bulanan */
public
double dapatPembayaranBulanan() {
double
sukuBungaBulanan = sukuBungaTahunan / 1200;
double
pembayaranBulanan = jumlahPinjaman * sukuBungaBulanan / (1 -
(Math.pow(1
/ (1 + sukuBungaBulanan), jumlahTahun * 12)));
return
pembayaranBulanan;
}
/**
Menghitung total pembayaran */
public
double dapatPembayaranTotal() {
double
pembayaranTotal = dapatPembayaranBulanan() * jumlahTahun * 12;
return
pembayaranTotal;
}
/**
Mengembalikan tanggal pinjaman */
public
java.util.Date dapatTanggalPinjaman() {
return
tanggalPinjaman;
}
}
|
Dari perspektif pengembang kelas,
suatu kelas didesain agar bisa digunakan oleh banyak konsumen. Agar dapat
digunakan pada aplikasi yang lebih luas, suatu kelas harus menyediakan cara
memodifikasi melalui konstruktor, bidang data, dan metode.
Kelas Hutang memiliki dua konstruktor, empat metode dapat, tiga metode tetapkan,
dan beberapa metode untuk menghitung pembayaran bulanan dan pembayaran total. Anda
bisa menciptakan suatu objek Hutang
menggunakan konstruktor tanpa-argumen atau menggunakan konstruktor dengan tiga
argumen: suku bunga tahunan, jumlah tahun, dan jumlah pinjaman. Ketika suatu
objek Hutang diciptakan, tanggalnya
disimpan pada bidang data tanggalPinjaman.
Metode dapatTanggalPinjaman
mengembalikan tanggal pembuatan pinjaman. Tiga metode dapat, dapatSukuBungaTahunan,
dapatJumlahTahun, dan dapatJumlahPinjaman, mengembalikan
secara berturut-turut suku bunga tahunan, jumlah tahun pembayaran, dan jumlah
pinjaman. Semua bidang data dan metode dalam kelas ini terikat dengan instans
kelas Hutang secara spesifik. Oleh
karena itu semua bidang data dan metode dalam kelas ini adalah variabel dan
metode instans.
10.6 Cara Berpikir Berorientasi
Objek
Bab 1-7 mengenalkan teknik
pemrograman elementer untuk menyelesaikan masalah menggunakan loop, metode, dan
array. Teknik pemrograman tersebut meletakkan pondasi yang kokoh untuk
pemrograman berorientasi objek. Kelas memberikan fleksibilitas dan modularitas
untuk membangung perangkat lunak yang dapat didaur-ulang atau dipakai kembali. Bagian
ini akan memperbaiki solusi terhadap suatu masalah yang diintroduksi pada Bab.
3 menggunakan pendekatan berorientasi objek. Dari perbaikan-perbaikan yang
dilakukan, Anda akan memperoleh pengetahuan akan perbedaan antara pemrograman
prosedural dengan pemrograman berorientasi objek. Anda juga diharapkan mampu
melihat beberapa keuntungan pengembangan kode yang dapat didaur-ulang
menggunakan kelas dan objek.
Kode3.5, HitungBMI.java, telah
menyajikan suatu program untuk menghitung indeks massa tubuh. Kode tersebut
tidak dapat digunakan kembali oleh program lain. Untuk membuatnya dapat
didaur-ulang, definisikan suatu metode statik untuk menghitung indeks massa
tubuh sebagai berikut:
public
static double dapatBMI(double berat, double tinggi)
Metode ini berguna untuk
menghitung BMI pada berat dan tinggi badan tertentu. Tetapi, metode ini
memiliki keterbatasan. Dimisalkan Anda ingin mengaitkan berat dan tinggi dengan
nama dan tanggal lahir seseorang, maka Anda perlu mendeklarasikan
variabel-variabel terpisah untuk menyimpan nilai-nilai ini. Cara ideal untuk
melakukannya adalah dengan menciptakan suatu objek yang memuat nilai-nilai
tersebut. Karena nilai-nilai tersebut terikat dengan objek individual tertentu,
maka harus disimpan dalam bidang-bidang data instans. Anda bisa mendefinisikan
suatu kelas bernama BMI, seperti
yang ditampilkan pada Gambar 10.5.
Gambar
10.5
Kelas BMI mengenkapsulasi informasi
BMI.
Asumsikan bahwa kelas BMI telah
tersedia, kode10.3 menyajikan suatu program uji yang menggunakan kelas ini.
Kode10.3 GunakanKelasBMI.java
1
2
3
4
5
6
7
8
9
10
11
|
public class GunakanKelasBMI {
public
static void main(String[] args) {
BMI
bmi1 = new BMI("Krista Simanungkalit", 18, 145, 70);
System.out.println("BMI
untuk "+ bmi1.dapatNama() + " adalah "
+
bmi1.dapatBMI() + " "+ bmi1.dapatStatus());
BMI
bmi2 = new BMI("Tobat Sinaga", 215, 70);
System.out.println("BMI
untuk "+ bmi2.dapatNama() + " adalah "
+
bmi2.dapatBMI() + " "+ bmi2.dapatStatus());
}
}
|
Keluaran
BMI untuk Krista Simanungkalit adalah 20.81 normal
BMI untuk Tobat Sinaga adalah 30.85 sangat gemuk
Baris 3 menciptakan suatu objek bmi1 untuk Krista Simanungkalit dan
baris 7 menciptakan suatu objek bmi2
untuk Tobat Sinaga. Anda bisa menggunakan metode-metode instans dapatNama(), dapatBMI(), dan dapatStatus()
untuk mengembalikan informasi BMI di dalam suatu objek BMI.
Kelas BMI dapat diimplementasikan pada kode 10.4 sebagai berikut:
Kode10.4 BMI.java
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
|
public class BMI {
private
String nama;
private
int usia;
private
double berat; // dalam pound
private
double tinggi; // dalam inci
public
static final double KILOGRAM_PER_POUND = 0.45359237;
public
static final double METER_PER_INCI = 0.0254;
public
BMI(String nama, int usia, double berat, double tinggi)
{
this.nama
= nama;
this.usia
= usia;
this.berat
= berat;
this.tinggi
= tinggi;
}
public
BMI(String nama, double berat, double tinggi) {
this(nama, 20, berat, tinggi);
}
public double dapatBMI() {
double
bmi = berat * KILOGRAM_PER_POUND /
((tinggi
* METER_PER_INCI) * (tinggi * METER_PER_INCI));
return
Math.round(bmi * 100) / 100.0;
}
public
String dapatStatus() {
double
bmi = dapatBMI();
if
(bmi < 16)
return
"sangat kurus";
else
if (bmi < 18)
return
"kurus";
else
if (bmi < 24)
return
"normal";
else
if (bmi < 29)
return
"gemuk";
else
if (bmi < 35)
return
"sangat gemuk";
else
return
"terlalu gemuk";
}
public
String dapatNama() {
return
nama;
}
public
int dapatUsia() {
return
usia;
}
public
double dapatBerat() {
return
berat;
}
public
double dapatTinggi() {
return
tinggi;
}
}
|
Formula matematika untuk
menghitung BMI diberikan menggunakan berat dan tinggi diberikan pada bagian
3.10. Metode instans dapatBMI()
mengembalikan nilai BMI. Karena berat dan tinggi adalah bidang data instans di
dalam objek, metode dapatBMI() dapat
menggunakan kedua bidang data tersebut untuk menghitung BMI untuk objek.
Metode instans dapatStatus() mengembalikan suatu
string yang merepresentasikan BMI. Interpretasinya juga diberikan pada bagian
3.10.
Contoh ini mendemonstrasikan
beberapa keuntungan paradigma berorientasi objek dibandingkan dengan paradigma
prosedural. Paradigma prosedural berfokus pada perancangan metode. Paradigma
berorientasi objek menggandeng data dan metode di dalam objek. Perancangan
perangkat lunak menggunakan paradigma berorientasi objek berfokus pada objek
dan operasi-operasi pada objek. Pendekatan berorientasi objek menggabungkan
kekuatan paradigma prosedural dengan suatu dimensi tambahan yang
mengintegrasikan data dengan operasi-operasi ke dalam objek.
Dalam pemrograman prosedural, data
dan operasi terpisah, dan metodologi ini membutuhkan pengiriman data kepada
metode. Pemrograman berorientasi objek menempatkan data dan operasi-operasi
yang melekat dengan data tersebut di dalam suatu objek. Pendekatan ini mampu
menyelesaikan masalah yang ada pada pemrograman prosedural. Pendekatan
pemrograman berorientasi objek bercermin pada apa yang terjadi di dunia nyata,
dimana semua objek berhubungan dengan atribut dan aktivitas. Menggunakan objek
memampukan pendaur-ulangan kode dan membuat program lebih mudah dipelihara dan
dimodifikasi.
10.7 Komposisi Objek
Suatu objek dapat memuat objek
yang lain. Relasi antar keduanya disebut dengan komposisi. Pada kode10.1, Anda mendefinisikan suatu kelas BMI untuk memuat suatu bidang data String. Relasi antara BMI dan String merupakan suatu komposisi.
Komposisi sebenarnya adalah suatu
kasus spesial dari relasi agregasi. Agregasi memodelkan hubungan adalah-suatu dan merepresentasikan relasi kepemilikan antara dua objek.
Objek pemilik disebut dengan objek
pengagregat dan kelasnya dinamai dengan kelas
pengagregat. Objek subjek atau objek yang dimiliki disebut dengan objek teragregat dan kelasnya dinamai
dengan kelas teragregat.
Suatu objek bisa saja dimiliki
oleh beberapa objek pengagregat. Jika suatu objek secara eksklusif dimiliki
oleh satu objek, maka relasi antara kedua objek tersebut disebut dengan
komposisi. Sebagai contoh, “seorang siswa
memiliki suatu nama” adalah suatu relasi komposisi antara kelas Siswa dengan kelas Nama, sedangkan “seorang
siswa memiliki suatu alamat” adalah suatu relasi agregasi antara kelas Siswa dengan kelas Alamat, karena suatu alamat bisa dipakai bersama oleh beberapa
siswa. Dalam UML, suatu diamond terisi dilekatkan pada suatu kelas pengagregat
(misalnya, kelas Siswa) untuk
menandai hubungan komposisi dengan suatu kelas teragregat (misalnya, kelas Nama), dan suatu diamond kosong
dilekatkan pada suatu kelas pengagregat (misalnya, kelas Siswa) untuk menandai hubungan agregasi dengan suatu kelas
teragregat (misalnya, kelas Alamat),
seperti yang ditampilkan pada Gambar 10.6.
Gambar
10.6
Seorang siswa memiliki suatu nama dan suatu alamat
Setiap kelas yang terlibat di
dalam suatu relasi dapat menentukan multiplisitas. Suatu multiplisitas dapat
berupa suatu angka atau suatu interval untuk menentukan berapa banyak objek
kelas yang terlibat di dalam relasi tersebut. Karakter * berarti banyaknya objek yang terlibat adalah tak-terhingga, dan
interval m..n berarti bahwa jumlah
objek yang terlibat seharusnya adalah antara m sampai n. Pada Gambar
10.6, setiap siswa hanya memiliki satu alamat, dan setiap alamat bisa dipakai oleh
sampai dengan 3 siswa. Setiap siswa hanya memiliki satu nama, dan setiap nama
unik untuk setiap mahasiswa.
Suatu relasi agregasi biasanya
direpresentasikan sebagai suatu bidang data di dalam kelas pengagregat. Sebagai
contoh, relasi pada Gambar 10.6 dapat disajikan sebagai berikut:
Agregasi dapat terjadi antar objek
sesama kelas. Sebagai contoh, seseorang dapat memiliki seorang supervisor. Ini
diilustrasikan pada Gambar 10.7.
Gambar
10.7
Satu orang dapat memiliki satu supervisor
Dalam relasi, “seseorang memiliki
seorang supervisor”, seperti ditunjukkan pada Gambar 10.7, seorang supervisor
dapat direpresentasikan sebagai suatu bidang data di dalam kelas Orang, sebagai berikut:
public class Orang
{
// Tipe data
adalah kelasnya sendiri
private Orang supervisor;
...
}
Jika seseorang memiliki beberapa supervisor, seperti yang
ditunjukkan pada Gambar 10.8a, maka Anda bisa menggunakan suatu array untuk
menyimpan beberapa supervisor, seperti ditampilkan pada Gambar 10.8b:
Gambar 10.8 Seseorang bisa memiliki beberapa supervisor
10.8 Mendesain Kelas Pelajaran
Filosopi buku ini adalah mengajar
dengan contoh dan belajar dengan latihan. Buku ini menyediakan banyak
contoh untuk mendemonstrasikan pemrograman berorientasi objek. Tiga bagian ke
depan akan menawarkan beberapa contoh dalam mendesain kelas.
Dimisalkan Anda ingin mengolah informasi tentang pelajaran.
Setiap pelajaran memiliki suatu nama dan para siswa yang terdaftar. Anda
diharapkan bisa menghapus/menambah seorang siswa dari/ke pelajaran tertentu.
Anda bisa menggunakan suatu kelas untuk memodelkan pelajaran, seperti tertampil
pada Gambar 10.9.
Gambar 10.9 Kelas Pelajaran
memodelkan pelajaran-pelajaran
Suatu objek Pelajaran
dapat diciptakan menggunakan konstruktor Pelajaran(String
namaPelajaran) dengan melewatkan suatu nama pelajaran. Anda bisa
menambahkan siswa-siswa kepada pelajaran menggunakan metode tambahSiswa(String siswa), menghapus
seorang siswa dari pelajaran menggunakan metode buangSiswa(String siswa), dan mengembalikan semua siswa pada
pelajaran menggunakan metode dapatSiswa().
Dimisalkan bahwa kelas Pelajaran
telah tersedia, kode10.5 disajikan sebagai suatu program uji untuk menciptakan
dua pelajaran dan menambahkan siswa kepada keduanya.
Kode10.5 UjiPelajaran.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class UjiPelajaran {
public
static void main(String[] args) {
Pelajaran pelajaran1 = new
Pelajaran("Fisika");
Pelajaran pelajaran2 = new
Pelajaran("Biologi");
pelajaran1.tambahSiswa("Vivian
Siahaan");
pelajaran1.tambahSiswa("Patricia
Butet");
pelajaran1.tambahSiswa("John
Sangar");
pelajaran2.tambahSiswa("Vivian
Siahaan");
pelajaran2.tambahSiswa("Hasiholan
Stark");
System.out.println("Jumlah
siswa dalam pelajaran1: "
+
pelajaran1.dapatJumlahSiswa());
String[]
siswa = pelajaran1.dapatSiswa();
for
(int i = 0; i < pelajaran1.dapatJumlahSiswa();
i++)
System.out.print(siswa[i]
+ ", ");
System.out.println();
System.out.print("Jumlah
siswa dalam pelajaran2: "
+
pelajaran2.dapatJumlahSiswa());
}
}
|
Keluaran
Jumlah siswa
dalam pelajaran1: 3
Vivian
Siahaan, Patricia Butet, John Sangar,
Jumlah siswa
dalam pelajaran2: 2
Kelas Pelajaran
diimplementasikan pada kode10.6, yang menggunakan suatu array untuk menyimpan
siswa-siswa untuk pelajaran tertentu. Metode tambahSiswa (baris 10) menambahkan seorang siswa ke dalam array.
Kapanpun seorang siswa baru ditambahkan kepada pelajaran tertentu, jumlahSiswa diinkremen. Metode
dapatSiswa mengembalikan array tersebut. Metode buangSiswa (baris 27) ditinggalkan kosong sebagai latihan.
Kode10.6 Pelajaran.java
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
|
public class Pelajaran {
private
String namaPelajaran;
private
String[] siswa = new String[100];
private
int jumlahSiswa;
public
Pelajaran(String namaPelajaran) {
this.namaPelajaran
= namaPelajaran;
}
public void tambahSiswa(String siswa1) {
siswa[jumlahSiswa]
= siswa1;
jumlahSiswa++;
}
public String[] dapatSiswa() {
return
siswa;
}
public int dapatJumlahSiswa() {
return
jumlahSiswa;
}
public String dapatNamaPelajaran() {
return
namaPelajaran;
}
public void buangSiswa(String siswa) {
//
dibiarkan kosong untuk latihan
}
}
|
Ukuran array ditetapkan 100 (baris 3). Ketika Anda menciptakan
suatu objek Pelajaran, suatu objek
array diciptakan. Secara sederhana dapat dikatakan bahwa objek Pelajaran memuat suatu array.
Pengguna dapat menciptakan suatu objek Pelajaran, dan memanipulasinya melalui metode-metode publik tambahSiswa, buangSiswa, dapatJumlahSiswa,
dan dapatSiswa. Namun, pengguna
tidak perlu mengetahui bagaimana metode-metode tersebut diimplementasikan. Kelas
Pelajaran mengenkapsulasi
implementasi internal.
10.9 Mendesain Kelas untuk
Tumpukan
Ingat bahwa suatu tumpukan merupakan suatu struktur data yang
memuat data dengan gaya last-in, first-out, seperti yang ditampilkan pada
Gambar 10.10:
Gambar 10.10 Suatu tumpukan yang memuat data dengan gaya last-in,
first-out
Tumpukan memiliki banyak terapan. Sebagai contoh, kompiler
menggunakan suatu tumpukan untuk mengolah pembagian metode. Ketika suatu metode
dipanggil, parameter dan variabel lokalnya didorong ke dalam suatu tumpukan. Ketika
suatu metode memanggil metode lain, parameter dan variabel lokal dari metode
yang baru didorong ke dalam tumpukan. Ketika metode yang dipanggil selesai dieksekusi
dan kembali kepada metode pemanggil, memori yang diokupasi dibebaskan dari
tumpukan.
Anda bisa mendefinisikan suatu kelas untuk memodelkan tumpukan.
Untuk alasan penyederhanaan, diasumsikan tumpukan memuat nilai-nilai int, dan diberikan nama TumpukanInteger. Diagram UML kelas TumpukanInteger ditampilkan pada Gambar
10.11.
Diasumsikan implementasi kelas TumpukanInteger telah tersedia, pada kode10.7 disediakan suatu
program uji untuk menggunakan kelas tersebut untuk menciptakan suatu tumpukan
(baris 3), menyimpan sepuluh integer 0, 1, 2, ..., dan 9 (baris 6), dan
menampilkannya dalam urutan yang terbalik (baris 9).
Gambar 10.11 Kelas TumpukanInteger
mengenkapsulasi penyimpanan tumpukan dan menyediakan beberapa operasi untuk
memanipulasi tumpukan
Kode10.7 UjiTumpukanInteger.java
1
2
3
4
5
6
7
8
9
10
11
|
public class UjiTumpukanInteger {
public
static void main(String[] args) {
TumpukanInteger tumpukan = new
TumpukanInteger();
for
(int i = 0; i < 10; i++)
tumpukan.dorong(i);
while
(!tumpukan.kosong())
System.out.print(tumpukan.hapus()
+ " ");
}
}
|
Bagaimana Anda mengimplementasikan kelas TumpukanInteger? Elemen-eleman di dalam tumpukan disimpan di dalam
suatu array bernama elemen. Ketika
Anda menciptakan suatu tumpukan, array tersebut juga diciptakan. Konstruktor
tanpa-argumen menciptakan suatu array dengan kapasitas default 16. Variabel ukuran menghitung jumlah elemen di
dalam tumpukan, size – 1 adalah
indeks elemen teratas di dalam tumpukan, seperti tertampil pada Gambar 10.12. Untuk
suatu tumpukan kosong, ukuran adalah
0.
Kelas TumpukanInteger diimplementasikan pada kode10.8. Metode-metode
kosong(), intip(), hapus(), dan dapatUkuran() mudah untuk
diimplementasikan. Untuk mengimplementasikan dorong(int nilai), nilai
ditugaskan kepada elemen[ukuran]
jika ukuran < kapasitas (baris
24). Jika tumpukan penuh (misalnya, ukuran
>= kapasitas), suatu array baru diciptakan dengan kapasitas dua kali
dari kapasitas sekarang (baris 19), isi array sekarang disalin kepada array
yang baru (baris 20), dan referensi array baru ditugaskan kepada array sekarang
di dalam tumpukan (baris 21).
Gambar 10.12 Kelas TumpukanInteger
mengenkapsulasi penyimpanan tumpukan dan menyediakan beberapa operasi untuk
memanipulasi tumpukan
Kode10.8 TumpukanInteger.java
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
|
public class TumpukanInteger {
private
int[] elemen;
private
int ukuran;
public
static final int KAPASITAS_DEFAULT = 16;
/**
Menciptakan suatu tumpukan dengan kapasitas default 16 */
public TumpukanInteger(){
this(KAPASITAS_DEFAULT);
}
/** Menciptakan suatu tumpukan dengan kapasitas
tertentu */
public TumpukanInteger(int kapasitas){
elemen
= new int[kapasitas];
}
/**
Mendorong suatu integer baru ke dalam tumpukan */
public
void dorong(int nilai) {
if
(ukuran >= elemen.length) {
int[]
temp = new int[elemen.length * 2];
System.arraycopy(elemen,
0, temp, 0, elemen.length);
elemen
= temp;
}
elemen[ukuran++]
= nilai;
}
/**
Mengembalikan dan menghapus elemen teratas dari tumpukan */
public
int hapus() {
return
elemen[--ukuran];
}
/**
Mengembalikan elemen teratas dari tumpukan */
public
int intip() {
return
elemen[ukuran - 1];
}
/**
Menguji apakah tumpukan kosong */
public
boolean kosong() {
return
ukuran == 0;
}
/**
Mengembalikan jumlah elemen di dalam tumpukan */
public
int dapatUkuran() {
return
ukuran;
}
}
|
10.10 Mendesain Kelas TebakTanggal
Kode3.3, TebakUltah.java, dan kode7.6,
TebakUltahMenggunakanArray.java, telah menyajikan dua program untuk menebak
hari ulang tahun seseorang. Kedua program menggunakan data sama yang
dikembangkan menggunakan paradigma prosedural. Mayoritas kode pada kedua
program tersebut adalah untuk mendefinisikan lima himpunan data. Anda tidak
bisa menggunakan kembali kode pada kedua program itu. Untuk membuat program
dapat didaur-ulang, didesain kelas untuk mengenkapsulasi data, seperti
didefinisikan pada Gambar 10.13.
Gambar 10.13 Kelas TebakTanggal
mendefinisikan data untuk menebak hari ulang tahun
Perhatikan bahwa dapatNilai
didefinisikan sebagai suatu metode statik karena tidak bergantung pada objek
kelas TebakTanggal tertentu. Kelas TebakTanggal mengenkapsulasi tanggal sebagai anggota privat.
Pengguna kelas ini tidak perlu mengetahui bagaimana diimplementasikan. Semua
yang perlu diketahui oleh pengguna adalah bagaimana menggunakan metode dapatNilai mengakses tanggal.
Pemanggilan metode dapatNilai(noHimp,
baris, kolom) akan memberikan nilai balik berupa tanggal pada baris dan
kolom tertentu. Misalnya, dapatNilai(1,
0, 0) menghasilkan 2.
Diasumsikan bahwa kelas TebakTanggal
telah tersedia, kode10.9 disajikan sebagai suatu program uji yang menggunakan
kelas ini.
Kode10.9 GunakanKelasTebakTanggal.java
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
|
import java.util.Scanner;
public class GunakanKelasTebakTanggal {
public
static void main(String[] args) {
int
tanggal = 0; // Tanggal yang akan ditentukan
int
jawaban;
//
Menciptakan Scanner
Scanner
masukan = new Scanner(System.in);
for
(int i = 0; i < 5; i++) {
System.out.println("Apakah ultah Anda dalam
himpunan"
+ (i + 1) + "?");
for
(int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++)
System.out.print(TebakTanggal.dapatNilai(i,
j, k) + " ");
System.out.println();
}
System.out.print("\nMasukkan
o untuk Tidak dan 1 Untuk Ya: ");
jawaban
= masukan.nextInt();
if
(jawaban == 1)
tanggal += TebakTanggal.dapatNilai(i, 0, 0);
}
System.out.println("Hari
Ultah Anda adalah " + tanggal);
}
}
|
Keluaran
Apakah ultah
Anda dalam himpunan1?
1 3 5 7
9 11 13 15
17 19 21 23
25 27 29 31
Masukkan o
untuk Tidak dan 1 Untuk Ya: 1
Apakah ultah
Anda dalam himpunan2?
2 3 6 7
10 11 14 15
18 19 22 23
26 27 30 31
Masukkan o
untuk Tidak dan 1 Untuk Ya: 0
Apakah ultah
Anda dalam himpunan3?
4 5 6 7
12 13 14 15
20 21 22 23
28 29 30 31
Masukkan o
untuk Tidak dan 1 Untuk Ya: 1
Apakah ultah
Anda dalam himpunan4?
8 9 10 11
12 13 14 15
24 25 26 27
28 29 30 31
Masukkan o
untuk Tidak dan 1 Untuk Ya: 1
Apakah ultah
Anda dalam himpunan5?
16 17 18 19
20 21 22 23
24 25 26 27
28 29 30 31
Masukkan o
untuk Tidak dan 1 Untuk Ya: 0
Hari Ultah
Anda adalah 13
Karena dapatNilai
adalah suatu metode statik, Anda tidak perlu menciptakan suatu objek untuk
memanggilnya. Metode TebakTanggal.dapatNilai(i,
j, k) mengembalikan tanggal pada baris j
dan kolom k dalam himpunan i.
Kelas TebakTanggal
dapat diimplementasikan pada kode10.10.
Kode10.10 TebakTanggal.java
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
|
public class TebakTanggal {
private final static int[][][] tanggal = {
{{
1, 3, 5, 7},
{
9, 11, 13, 15},
{17,
19, 21, 23},
{25,
27, 29, 31}},
{{
2, 3, 6, 7},
{10,
11, 14, 15},
{18,
19, 22, 23},
{26,
27, 30, 31}},
{{
4, 5, 6, 7},
{12,
13, 14, 15},
{20,
21, 22, 23},
{28,
29, 30, 31}},
{{
8, 9, 10, 11},
{12,
13, 14, 15},
{24,
25, 26, 27},
{28,
29, 30, 31}},
{{16,
17, 18, 19},
{20,
21, 22, 23},
{24,
25, 26, 27},
{28,
29, 30, 31}}};
/**
Mencegah pengguna dalam menciptakan objek TebakTanggal */
private TebakTanggal() {
}
/** Mengembalikan
suatu tanggal pada baris dan kolom tertentu dari himpunan yang diberikan */
public static int dapatNilai(int noHimp, int k, int
j) {
return
tanggal[noHimp][k][j];
}
}
|
No comments:
Post a Comment