Membebani Metode dan Konstruktor
Anda akan melanjutkan untuk memperbaiki kelas Pecahan. Jika diberikan kelas Pecahan seperti pada bentuk sekarang, bagaimana sebuah programer klien mengekspresikan ekspresi matematik berikut?
f3 = 2/3 + 9;
Satu cara adalah dengan mengkonversi integer 9 menjadi sebuah pecahan (9/1) dan kemudian menggunakan metode jumlah():
Pecahan f1, f2, f3; f1 = new Pecahan(2, 3); f2 = new Pecahan(9, 1); f3 = f1.jumlah(f2)
Memang hal itu tidak buruk, tetapi akan lebih baik jika Anda menuliskan seperti ini:
Pecahan f1, f2; f1 = new Pecahan(2, 3); f3 = f1.jumlah(9);
Dengan kata lain, Anda tidak melewatkan sebuah objek Pecahan, tetapi hanya melewatkan sebuah nilai integer. Tentu, dengan kelas Pecahan saat ini, statemen:
f3 = f1.jumlah(9);
akan menyebabkan error karena tidak ada metode yang cocok yang didefinisikan di dalam kelas. Jadi, apa yang Anda inginkan di sini adalah memiliki dua versi metode jumlah(), satu yang menerima sebuah objek Pecahan sebagai argumennya dan satu lagi yang menerima sebuah integer sebagai argumennya. Berikut adalah kedua definisi tersebut:
//Versi 1 public Pecahan jumlah(Pecahan pecah) { //sama seperti sebelumnya } //Versi 2 public Pecahan jumlah(int bilangan) { Pecahan jum; int a, b, c, d; a = getNumerator(); b = getDenominator(); c = bilangan; d = 1; jum = new Pecahan(a*d + c*b, b*d); return jum; }
Jadi, Anda bisa mengujinya dengan kelas berikut:
//Menguji pembebanan metode public class UjiPecahanPembebananMetode { public static void main(String args[]) { Pecahan f1, f3; f1 = new Pecahan(2, 3); f3 = f1.jumlah(9); System.out.println(f1.toString() + " + 9 = " + f3.toString()); } }
Keluaran dari program ini diberikan berikut:
2/3 + 9 = 29/3
Dengan metode jumlah() yang kedua, Anda sekarang memiliki dua metode di dalam kelas Pecahan yang memiliki nama sama. Ini bukanlah masalah sepanjang beberapa aturan dipenuhi. Metode-metode yang memiliki nama sama disebut dengan metode-metode terbeban.
Sejumlah nama dapat memiliki nama sama sepanjang salah satu dari dua aturan ini dipenuhi:
- Memiliki jumlah parameter berbeda.
- Parameter berbeda tipe data ketika jumlah parameter sama.
public void metodeKu(int x, int y) { ... } public void metodeKu(int x) { ... }
Lebih formal dapat dikatakan bahwa dua metode dapat dibebani jika keduanya tidak memiliki sidik yang sama. Sidik metode merujuk pada nama metode dan banyak dan tipe data parameternya. Kedua metode metodeKu memiliki sidik berbeda karena banyak parameter yang dimiliki berbeda.
Dua metode tidak bisa dibebani bila hanya tipe data dari nilai balik metode yang berbeda karena itu berarti kedua metode memiliki sidik yang sama. Sebagai contoh, dua metode berikut tidak bisa didefinisikan pada kelas yang sama:
public double getInfo(String item) { ... } public int getInfo(String item) { ... }
Sekarang, lihat kembali metode jumlah() yang kedua. Daripada mendefinisikannya seperti sebelumnya, Anda dapat mendefinisikannya dengan memanggil metode jumlah() yang pertama:
//Versi 2 yang lebih ringkas public Pecahan jumlah(int bilangan) { Pecahan pecah = new Pecahan(bilangan, 1); Pecahan jum = jumlah(pecah); //memanggil metode jumlah() versi 1 return jum; }
Dengan cara yang sama, Anda bisa juga membebani metode bagi(), kali(), dan kurang() seperti berikut:
//Versi 2 bagi() yang ringkas public Pecahan bagi(int bilangan) { Pecahan pecah = new Pecahan(bilangan, 1); Pecahan hasil = bagi(pecah); //memanggil metode bagi() versi 1 return hasil; } //Versi 2 kali() yang ringkas public Pecahan kali(int bilangan) { Pecahan pecah = new Pecahan(bilangan, 1); Pecahan hasil = kali(pecah); //memanggil metode kali() versi 1 return hasil; } //Versi 2 kurang() yang ringkas public Pecahan kurang(int bilangan) { Pecahan pecah = new Pecahan(bilangan, 1); Pecahan hasil = kurang(pecah); //memanggil metode kurang() versi 1 return hasil; }
Jika digunakan pada kelas penguji seperti berikut, Anda bisa merasakan manfaat dari pembebanan metode:
//Menguji pembebanan metode public class UjiPecahanPembebananMetode { public static void main(String args[]) { Pecahan f1, f3; //Menguji pembebanan pada metode jumlah() f1 = new Pecahan(2, 3); f3 = f1.jumlah(9); System.out.println(f1.toString() + " + 9 = " + f3.toString()); //Menguji pembebanan pada metode bagi() f1 = new Pecahan(2, 3); f3 = f1.bagi(9); System.out.println(f1.toString() + " / 9 = " + f3.toString()); //Menguji pembebanan pada metode kali() f1 = new Pecahan(2, 3); f3 = f1.kali(9); System.out.println(f1.toString() + " * 9 = " + f3.toString()); //Menguji pembebanan pada metode kurang() f1 = new Pecahan(2, 3); f3 = f1.kurang(9); System.out.println(f1.toString() + " - 9 = " + f3.toString()); } }
Jika dijalankan, program di atas akan menghasilkan keluaran berikut:
2/3 + 9 = 29/3 2/3 / 9 = 2/27 2/3 * 9 = 18/3 2/3 - 9 = -25/3
Membebani Konstruktor
Sampai saat ini, kelas yang telah didefinisikan hanya memuat satu konstruktor. Tetapi konstruktor juga merupakan metode, jadi, dapat pula dibebani. Bahkan, adalah hal yang sangat umum untuk mendefinisikan sejumlah konstruktor pada sebuah kelas. Aturan-aturan yang berlaku pada pembebanan metode juga berlaku pada pembebanan konstruktor. Pendefinisian sejumlah konstruktor untuk sebuah kelas memberikan fleksibilitas bagi programer dalam menciptakan objek-objek kelas. Programer klien dapat memilih salah satu dari beberapa konstruktor yang cocok dengan kebutuhannya. Berikut adalah empat konstruktor (termasuk satu konstruktor yang telah didefinisikan sebelumnya):
//Konstruktor tanpa parameter public Pecahan() { //menciptakan objek Pecahan dengan nilai awal 0/1 setNumerator(0); setDenominator(1); } //Konstruktor satu-parameter int public Pecahan(int bilangan) { //menciptakan objek pecahan dengan nilai awali bilangan/1 setNumerator(bilangan); setDenominator(1); } //Konstruktor satu-parameter objek Pecahan public Pecahan(Pecahan pecah) { //konstruktor penyalin setNumerator(pecah.getNumerator()); setDenominator(pecah.getDenominator()); } //Konstruktor dua-parameter int public Pecahan(int num, int denom) { //konstruktor yang telah didefinisikan sebelumnya setNumerator(num); setDenominator(denom); }
Anda dapat menguji keempat konstruktor ini dengan kelas penguji sebagai berikut:
//Menguji pembebanan Konstruktor public class UjiPembebananKonstruktor { public static void main(String args[]) { Pecahan f1, f2, f3, f4; //Memanggil konstruktor tanpa parameter f1 = new Pecahan(); System.out.println("Isi dari objek f1 = " + f1.toString()); //Memanggil konstruktor satu-parameter int f2 = new Pecahan(7); System.out.println("Isi dari objek f2 = " + f2.toString()); //Memanggil konstruktor penyalin satu-parameter objek Pecahan f3 = new Pecahan(f1); System.out.println("Isi dari objek f3 = f1 = " + f3.toString()); //Memanggil konstruktor dua-parameter int f4 = new Pecahan(3,7); System.out.println("Isi dari objek f1 = " + f4.toString()); } }
Jika dijalankan, program di atas akan menghasilkan keluaran berikut:
Isi dari objek f1 = 0/1 Isi dari objek f2 = 7/1 Isi dari objek f3 = f1 = 0/1 Isi dari objek f1 = 3/7
Sintaksis untuk memanggil sebuah konstruktor dari konstruktor lain pada kelas yang sama adalah:
this(<daftar-parameter>);
Konstruktor dengan daftar parameter yang cocok akan dipanggil. Anda dapat menambahkan statemen-statemen lain setelah statemen ini di dalam sebuah konstruktor, tetapi bukan sebelumnya. Dengan kata lain, pemanggilan terhadap this pada sebuah konstruktor harus menjadi statemen pertama dari konstruktor.
Berikut merupakan keempat konstruktor yang telah didefinisikan di atas dengan versi menggunakan katakunci this:
//Konstruktor tanpa parameter public Pecahan() { //menciptakan objek Pecahan dengan nilai awal 0/1 this(0,1); //memanggil konstruktor dua-parameter int } //Konstruktor satu-parameter int public Pecahan(int bilangan) { //menciptakan objek pecahan dengan nilai awali bilangan/1 this(bilangan,1); //memanggil konstruktor dua-parameter int } //Konstruktor satu-parameter objek Pecahan public Pecahan(Pecahan pecah) { //konstruktor penyalin //memanggil konstruktor dua-parameter int this(pecah.getNumerator(), pecah.getDenominator()); } //Konstruktor dua-parameter int public Pecahan(int num, int denom) { //konstruktor yang telah didefinisikan sebelumnya setNumerator(num); setDenominator(denom); }
Anda bisa menguji keempat konstruktor ini dengan kelas penguji yang sama untuk mendapatkan keluaran program yang persis sama.
SOAL DAN JAWABAN:
Apakah ada konflik pada ketiga konstruktor berikut untuk KelasX?:
public KelasX(int X) { ... } public KelasY(float X) { ... } public KelasX(int Y) { ... }
JAWAB:
Ya, karena terdapat dua konstruktor KelasX yang memiliki sidik sama, yaitu konstrukor yang memiliki satu parameter int.
Definisikanlah sebuah kelas Siswa. Kelas ini memiliki anggota data nama. Definisikanlah dua konstruktor, satu tanpa argumen apapun dan konstruktor lain dengan nama siswa sebagai argumennya. Inisialisasi nama dengan nilai default “Tidak dikenal” untuk konstruktor tanpa argumen.
JAWAB:
Berikut adalah kelas Siswa yang memiliki dua konstruktor seperti yang diinginkan. Satu konstruktor tidak memiliki argumen apapun dan konstruktor lain memiliki nama siswa sebagai argumennya. Inisialisasi nama dengan nilai default “Tidak dikenal” untuk konstruktor tanpa argumen. Kelas ini juga dilengkapi dengan sebuah aksesor dan sebuah mutator. Kelas ini juga mendefinisikan ulang metode toString():
Anda bisa menuliskan kelas pengujinya sebagai berikut:
Ketika program di atas dijalankan, keluaran program yang dihasilkan adalah berikut:
Tulis-ulanglah konstruktor-konstruktor berikut, sehingga konstruktor pertama memanggil konstruktor kedua:
JAWAB:
Berikut adalah versi KelasSatu dimana konstruktor pertama memanggil konstruktor keduanya:
Ketika program di atas dijalankan, keluaran program yang dihasilkan adalah berikut:
class Siswa { private String nama; // Aksesor public String getNama( ) { return nama; } // Mutator public void setNama(String nama) { this.nama = nama; } //Konstruktor tanpa-parameter public Siswa() { this("Tidak Dikenali"); } //Konstruktor satu-parameter public Siswa(String nama) { setNama(nama); } public String toString( ) { return this.nama; } }
Anda bisa menuliskan kelas pengujinya sebagai berikut:
public class UjiSiswa { public static void main(String args[]) { Siswa s1, s2; //Menguji konstruktor tanpa-parameter s1 = new Siswa(); System.out.println("Nama siswa = " + s1.toString()); //Menguji konstruktor satu-parameter s2 = new Siswa("Vivian"); System.out.println("Nama siswa = " + s2.toString()); } }
Ketika program di atas dijalankan, keluaran program yang dihasilkan adalah berikut:
Nama siswa = Tidak Dikenali Nama siswa = Vivian
Tulis-ulanglah konstruktor-konstruktor berikut, sehingga konstruktor pertama memanggil konstruktor kedua:
public class KelasSatu { private int alfa, beta; public KelasSatu(int alfa) { this.alfa = alfa; this.beta = 0; } public KelasSatu(int alfa, int beta) { this.alfa = alfa; this.beta = beta; } }
JAWAB:
Berikut adalah versi KelasSatu dimana konstruktor pertama memanggil konstruktor keduanya:
public class UjiKelasSatu { public static void main(String args[]) { KelasSatu k1, k2; //Menguji konstruktor tanpa-parameter k1 = new KelasSatu(7); System.out.println(k1.toString()); //Menguji konstruktor satu-parameter k2 = new KelasSatu(3,5); System.out.println(k2.toString()); } }
Ketika program di atas dijalankan, keluaran program yang dihasilkan adalah berikut:
Nilai dari alfa dan beta = 7 dan 0 Nilai dari alfa dan beta = 3 dan 5