Friday, March 16, 2018

6. Lebih Lanjut Dengan Kelas dan Metode




Bab ini akan melanjutkan diskusi tentang metode dan kelas yang telah diawali pada bab sebelumnya. Bab ini akan mendiskusikan topik-topik yang berkaitan dengan metode, termasuk pembebanan, pelewatan parameter, dan rekursi. Bab ini kemudian akan kembali ke topik kelas, mendiskusikan kendali akses, penggunakan katakunci static, dan salah satu kelas paling penting dalam Java: String.


Pembebanan Metode
Dalam Java, Anda dimungkinkan untuk mendefinisikan dua atau lebih metode yang memiliki nama sama di dalam kelas yang sama pula, sepanjang deklarasi-deklarasi parameternya berbeda. Pada kasus tersebut, metode-metode itu dikatakan dibebani, dan proses tersebut dinamakan dengan pembebanan metode. Pembebanan metode merupakan salah satu cara bagaimana Java mendukung polimorfisme. Anda akan melihat bahwa pembebanan metode merupakan salah satu fitur Java yang paling menarik dan berguna.

Ketika sebuah metode terbeban dipanggil, Java menggunakan tipe data dan/atau banyak argument sebagai panduannya dalam menentukan versi dari metode terbeban mana yang sebenarnya memanggil. Jadi, metode-metode yang terbebani harus memiliki tipe data dan/atau banyak parameter yang berbeda. Ketike metode-metode terbeban memiliki tipe data nilai balik yang berbeda, tipe data nilai balik tersebut sendiri tidak cukup untuk membedakan dua versi metode. Ketika Java menjumpai sebuah pemanggilan terhadap sebuah metode terbeban, ia hanya perlu mengeksekusi versi metode dengan parameter-parameter yang cocok dengan argument-argumen yang dipakai pada pemanggilan metode.

Berikut adalah sebuah contoh sederhana yang mengilustrasikan pembebanan metode:

// Mendemonstrasikan pembebanan metode
class DemoPembebanan {
   void test() {
      System.out.println("Tidak ada parameter");
   }
   
   // Pembebanan test untuk satu parameter integer.
   void test(int a) {
      System.out.println("a: " + a);
   }
   
   // Pembebanan test untuk dua parameter integer.
   void test(int a, int b) {
      System.out.println("a dan b: " + a + " " + b);
   }
   
   // Pembebanan test untuk satu parameter double.
   double test(double a) {
      System.out.println("double a: " + a);
      return a*a;
   }
}

public class Pembebanan {
   public static void main(String args[]) {
   DemoPembebanan ob = new DemoPembebanan();
      double hasil;
  
      // memanggil semua versi dari test()
      ob.test();
      ob.test(10);
      ob.test(10, 20);
  
      hasil = ob.test(123.25);
      System.out.println("Hasil dari ob.test(123.25): " + hasil);
   }
}

Program ini menghasilkan keluaran berikut:

Tidak ada parameter
a: 10
a dan b: 10 20
double a: 123.25
Hasil dari ob.test(123.25): 15190.5625

Seperti yang dapat Anda lihat, test() dibebani empat kali. Versi pertama tidak mengambil parameter apapun, versi kedua mengambil satu parameter integer, versi ketiga mengambil dua parameter integer, dan versi keempat mengambil satu parameter double. Fakta bahwa versi keempat dari test() juga menghasilkan sebuah nilai balik tidak berperan apapun dalam pembebanan.

Ketika sebuah metode terbeban dipanggil, Java akan mencari kecocokan antara argument-argumen yang dipakai untuk memanggil metode dengan parameter-parameter pada definisi metode. Namun, kecocokan ini tidak harus selalu persis sama. Pada beberapa kasus, konversi tipe data otomatis dalam Java berperan penting pembebanan. Sebagai contoh, perhatikan program berikut:

// Konversi tipe data otomatis pada pembebanan.
class DemoPembebanan {
   void test() {
      System.out.println("Tanpa parameter");
   }
   
   // Membebani test untuk parameter dua integer.
   void test(int a, int b) {
      System.out.println("a dan b: " + a + " " + b);
   }
   
   //Membebani test untuk satu parameter double
   void test(double a) {
      System.out.println("Di dalam test(double) a: " + a);
   }
}

public class Pembebanan2 {
   public static void main(String args[]) {
      DemoPembebanan ob = new DemoPembebanan();
      int i = 88;
  
      ob.test();
      ob.test(10, 20);
      ob.test(i);     // ini akan memanggile test(double)
      ob.test(123.2); // ini akan memanggil test(double)
   }
}

Seperti yang dapat Anda lihat, versi dari DemoPembebanan ini tidak mendefinisikan test(int). Oleh karena itu, ketika test() dipanggil dengan satu argument integer di dalam Pembebanan, tidak ada metode yang cocok yang ditemukan. Namun, Java secara otomatis mengkonversi integer menjadi double, dan konversi ini dapat dipaki untuk melakukan pemanggilan. Oleh karena itu, setelah test(int) tidak ditemukan, Java mempromosikan i menjadi double dan kemudian memanggil test(double). Tentu, jika test(int) didefinisikan pada kelas Pembebanan, ia yang yang akan dipanggil. Java menerapkan konversi tipe data otomatis hanya jika tidak ditemukan kecocokan.


Membebani konstruktor
Selain pembebanan terhadap metode normal, Anda dapat pula membebani konstruktor. Kenyataannya, untuk kelas-kelas yang digunakan pada projek perangkat lunak di dunia nyata, pembebanan konstruktor merupakan hal biasa dilakukan. Untuk memahami mengapa, Anda perlu kembali ke kelas Kotak yang dikembangkan pada bab sebelumnya. Berikut adalah versi terakhir dari kelas Kotak:

class Kotak {
   double lebar;
   double tinggi;
   double dalam;
   
   //Ini konstruktor untuk kelas Kotak
   Kotak(double w, double h, double d) {
      lebar = w;
      tinggi = h;
      dalam = d;
   }
   
   // menampilkan volume kotak
   double volume() {
      return lebar*tinggi*dalam;
   }
}

Seperti yang dapat Anda lihat, konstruktor Kotak() memerlukan tiga parameter. Ini berarti bahwa semua deklarasi dari objek-objek Kotak harus melewatkan tiga argument kepada konstruktor Kotak(). Sebagai contoh, statemen berikut merupakan statemen tak valid:

Kotak ob = new Kotak();

Karena Kotak() memerlukan tiga argumen, hal ini cukup fatal. Ini membangkitkan pertanyaan penting. Bagaimana jika Anda hanya menginginkan sebuah kotak dan tidak mempedulikan (atau mengetahui) apa dimensi-dimensi awalnya di sini? Atau, bagaimana jika Anda ingin menginisialisasi sebuah kubik hanya dengan menetapkan satu nilai yang akan dipakai untuk ketiga dimensi?

Untunglah, solusi terhadap permasalahan-permasalahan ini cukup mudah: Anda hanya perlu membebani konstruktor Kotak sehingga ia bisa menanganinya. Berikut adalah sebuah program yang memuat versi terperbaiki dari Kotak:

/* Di sini, Kotak mendefinisikan tiga konstruktor untuk
   menginisialisasi dimensi-dimensi kotak dengan pelbaga cara.
*/
class Kotak {
   double lebar;
   double tinggi;
   double dalam;

   // konstruktor dipakai ketika semua dimensi diberikan
   Kotak(double w, double h, double d) {
      lebar = w;
      tinggi = h;
      dalam = d;
   }
   
   // konstruktir dipakai ketika tidak ada dimensi diberikan
   Kotak() {
      lebar = -1;    // menggunakan -1 untuk mengindikasikan
      tinggi = -1;   // sebuah kotak
      dalam = -1;    // yang tidak diinisialisasi
   }
   
   // konstruktor digunakan ketika kubik diciptakan
   Kotak(double pjg) {
      lebar = tinggi = dalam = pjg;
   }
   
   // menghitung dan menghasilkan volume
   double volume() {
      return lebar * tinggi * dalam;
   }
}

public class PembebananKonstruktor {
   public static void main(String args[]) {
      // menciptakan objek-objek kotak menggunakan pelbagai konstruktor
      Kotak kotakKu1 = new Kotak(10, 20, 15);
      Kotak kotakKu2 = new Kotak();
      Kotak kubikKu = new Kotak(7);
  
      double vol;
  
      // mendapatkan volume dari kotak pertama
      vol = kotakKu1.volume();
      System.out.println("Volume kotakKu1 = " + vol);
  
      // mendapatkan volume dari kotak kedua
      vol = kotakKu2.volume();
      System.out.println("Volume kotakKu2 = " + vol);
  
      // mendapatkan volume kubik
      vol = kubikKu.volume();
      System.out.println("Volume kubikKu = " + vol);
   }
}

Ketika program ini dijalankan, Anda akan melihat keluaran berikut:

Volume kotakKu1 = 3000.0
Volume kotakKu2 = -1.0
Volume kubikKu = 343.0

Seperti yang dapat Anda lihat, konstruktor terbeban yang tepat dipanggil didasarkan pada parameter-parameter yang diberikan ketika operator new dieksekusi.


Menggunakan Objek Sebagai Parameter
Sejauh ini, Anda hanya menggunakan tipe-tipe data sederhana sebagai parameter kepada metode. Anda bisa juga melewatkan objek kepada metode. Sebagai contoh, perhatikan program pendek berikut:

// Objek dapat dilewatkan kepada metode.
class Test {
   int a, b;

   Test(int i, int j) {
      a = i;
      b = j;
   }

   // menghasilkan true jika o sama dengan objek pemanggil
   boolean samaDengan(Test o) {
      if(o.a == a && o.b == b) return true;
      else return false;
   }
}

class PelewatanObjek {
   public static void main(String args[]) {
      Test ob1 = new Test(100, 22);
      Test ob2 = new Test(100, 22);
      Test ob3 = new Test(-1, -1);

      System.out.println("ob1 == ob2: " + ob1.samaDengan(ob2));
      System.out.println("ob1 == ob3: " + ob1.samaDengan(ob3));
   }
}

Program ini menghasilkan keluaran berikut:

ob1 == ob2: true
ob1 == ob3: false

Seperti yang dapat Anda lihat, metode samaDengan() di dalam kelas Test membandingkan ekualitas atas dua objek dan memberikan hasil. Jadi, metode ini membandingkan objek pemanggil dengan objek yang dilewatkan sebagai argumen. Jika kedua objek memuat nilai-nilai yang sama, maka metode ini menghasilkan true. Sebaliknya, ia menghasilkan false. Perhatikan bahwa parameter o pada samaDengan() menetapkan Test sebagai tipe datanya. Meskipun Test adalah tipe data kelas yang diciptakan program, ia dapat dipakai dengan cara sama seperti tipe-tipe data pustaka Java.

Salah satu penggunaan umum dari parameter objek adalah pelibatan konstruktor. Biasanya, Anda ingin menciptakan sebuah objek baru sehingga ia awalnya sama dengan objek yang telah ada. Untuk melakukannya, Anda perlu mendefinisikan sebuah konstruktor yang mengambil sebuah objek kelasnya sebagai parameter. Sebagai contoh, versi berikut dari Kotak dapat dipakai untuk membuat satu objek menginisialisasi objek lain:

// Di sini, Kotak mengijinkan satu objek menginisialisasi objek lain

class Kotak {
   double lebar;
   double tinggi;
   double dalam;

   /* Perhatikan konstruktor ini. Ia mengambil
      sebuah objek bertipe data Kotak.*/
   Kotak(Kotak ob) { // melewatkan objek kepada konstruktor
      lebar = ob.lebar;
      tinggi = ob.tinggi;
      dalam = ob.dalam;
   }
   
   // konstruktor dipakai ketika semua dimensi diberikan
   Kotak(double w, double h, double d) {
      lebar = w;
      tinggi = h;
      dalam = d;
   }
   
   // konstruktir dipakai ketika tidak ada dimensi diberikan
   Kotak() {
      lebar = -1;    // menggunakan -1 untuk mengindikasikan
      tinggi = -1;   // sebuah kotak
      dalam = -1;    // yang tidak diinisialisasi
   }
   
   // konstruktor digunakan ketika kubik diciptakan
   Kotak(double pjg) {
      lebar = tinggi = dalam = pjg;
   }
   
   // menghitung dan menghasilkan volume
   double volume() {
      return lebar * tinggi * dalam;
   }
}

public class PembebananKonstruktor2 {
   public static void main(String args[]) {
      // menciptakan objek-objek kotak menggunakan pelbagai konstruktor
      Kotak kotakKu1 = new Kotak(10, 20, 15);
      Kotak kotakKu2 = new Kotak();
      Kotak kubikKu = new Kotak(7);
      
      Kotak klonKu = new Kotak(kotakKu1); // menciptakan salinan dari kotakKu1
  
      double vol;
  
      // mendapatkan volume dari kotak pertama
      vol = kotakKu1.volume();
      System.out.println("Volume kotakKu1 = " + vol);
  
      // mendapatkan volume dari kotak kedua
      vol = kotakKu2.volume();
      System.out.println("Volume kotakKu2 = " + vol);
  
      // mendapatkan volume kubik
      vol = kubikKu.volume();
      System.out.println("Volume kubikKu = " + vol);
      
      // mendapatkan volume dari klon
      vol = klonKu.volume();
      System.out.println("Volume klonKu = " + vol);
   }
}


Selanjutnya  >>>


No comments: