Friday, March 16, 2018

6. Lebih Lanjut Dengan Kelas dan Metode Bagian 3




Anda dapat melihat, di dalam kelas Test, a menggunakan akses default, yang sama dengan public. Variabel b ditetapkan secara eksplisit sebagai public. Anggota c dideklarasikan private. Ini berarti bahwa c tidak dapat diakses oleh kode di luar kelasnya. Jadi, di dalam kelas UjiAkses, c tidak dapat diakses secara langsung. Ia harus diakses melalui metode public: setc() dan getc(). Jika Anda menghapus simbol komentar di awal baris berikut:

// ob.c = 100; // Error!

maka program tidak akan bisa dikompilasi karena pelanggaran akses.

Untuk melihat bagaimana kendali akses dapat diterapkan pada contoh yang lebih praktis, perhatikan versi terperbaiki dari kelas Tumpukan berikut seperti ditunjukkan di akhir Bab 5:

/* Sekarang, baik tumpuk maupun nitem dideklarasikan private.
 * Ini berarti bahwa keduanya tidak bisa diubah dari luar kelas
 */
class Tumpukan {
   private int tumpuk[] = new int[10];
   private int nitem;

   // Menginisialisasi tumpukan
   Tumpukan() {
	   nitem = -1;
   }

   // Menempatkan item ke atas tumpukan
   void push(int item) {
      if(nitem==9)
         System.out.println("Tumpukan penuh.");
      else
    	  tumpuk[++nitem] = item;
   }
   
   // Mengambil item dari tumpukan
   int pop() {
      if(nitem < 0) {
         System.out.println("Tumpukan kosong.");
         return 0;
      }
      else
         return tumpuk[nitem--];
   }
}

Seperti yang dapat Anda lihat, sekarang keduanya baik tumpuk, yang memuat tumpukan, dan nitem, yang merupakan indeks dari atas tumpukan, dideklarasikan private. Ini berarti keduanya tidak bisa diakses atau diubah kecuali melalui push() dan pop(). Dengan membuat nitem menjadi private, misalnya, hal ini dapat mencegah bagian lain dari program Anda secara tak sengaja menetapkan nilainya di luar akhir dari array tumpuk.

Program berikut mendemonstrasikan kelas Tumpukan yang telah diperbaiki. Anda bisa mencoba menghapus komentar untuk membuktikan bahwa anggota tumpuk dan nitem tidak bisa diakses:

public class UjiTumpukan {
   public static void main(String args[]) {
      Tumpukan tumpukan1 = new Tumpukan();
      Tumpukan tumpukan2 = new Tumpukan();
		
      // menempatkan sejumlah nilai ke atas tumpukan
      for(int i=0; i<10; i++) tumpukan1.push(i);
      for(int i=10; i<20; i++) tumpukan2.push(i);
		
      // mengambil nilai-nilai dari tumpukan
      System.out.println("Tumpukan pada tumpukan1:");
      for(int i=0; i<10; i++)
         System.out.println(tumpukan1.pop());
		
      System.out.println("Tumpukan pada tumpukan2:");
      for(int i=0; i<10; i++)
         System.out.println(tumpukan2.pop());
      
      // statemen-statemen ini tidak valid
      // tumpukan1.nitem = -2;
      // tumpukan2.tumpuk[3] = 100;
   }
}


Memahami static
Ada saatnya Anda ingin mendeklarasikan sebuah anggota kelas yang akan digunakan terbebas dari objek-objek lain dari kelas tersebut. Umumnya, sebuah anggota telas hanya bisa diakses dengan kaitannya dengan objek dari kelas tersebut. Namun, Anda dimungkinkan untuk menciptakan sebuah anggota yang digunakan sendiri, tanpa mereferensi ke objek tertentu. Untuk menciptakan anggota semacam itu, pendeklarasiannya harus diawali dengan katakunci static. Ketika sebuah anggota dideklarasikan static, ia dapat diakses sebelum objek apapun dari kelasnya diciptakan, dan tanpa menggunakan referensi ke objek apapun. Anda dapat mendeklarasikan static baik untuk metode maupun variabel kelas. Contoh umum dari sebuah anggota static adalah metode main(). Metode ini dideklarasikan static karena ia perlu dipanggil sebelum objek apapun diciptakan.

Variabel kelas yang dideklarasikan static merupakan variabel global. Ketika objek dari kelas itu diciptakan, tidak ada salinan dari variabel static yang diciptakan. Semua objek dari kelas tersebut memakai secara bersama variabel static pada kelas tersebut.

Metode yang dideklarasikan static memiliki beberapa keterbatasan:

  • Ia hanya dapat memanggil secara langsung metode static lainnya.
  • Ia hanya dapat mengakses secara langsung anggota data static.
  • a tidak dapat menggunakan this atau super. (Katakunci super berkaitan dengan pewarisan yang akan dibahas pada bab berikutnya).

Jika Anda perlu melakukan inisialisasi terhadap variabel-variabel static, Anda dapat mendeklarasikan sebuah blok static yang dieksekusi hanya sekali, ketika kelas pertama kali dimuat. Contoh berikut menunjukkan sebuah kelas yang memiliki sebuah metode static, beberapa variabel static, dan sebuah blok inisialisasi static:

// Mendemonstrasikan variabel, metode, dan blok statis.
public class GunakanStatic {
   static int a = 3;
   static int b;

   static void metode(int x) {
      System.out.println("x = " + x);
      System.out.println("a = " + a);
      System.out.println("b = " + b);
   }
	
   static {
      System.out.println("Blok statis diinisialisasi.");
      b = a * 4;
   }
	
   public static void main(String args[]) {
	   metode(42);
   }
}

Ketika dijalankan, program ini menghasilkan keluaran berikut:

Blok statis diinisialisasi.
x = 42
a = 3
b = 12

Ketika kelas GunakanStatic dimuat, semua statemen static dijalankan. Pertama, a ditetapkan bernilai 3, kemudian blok static dieksekusi, yang menampilkan sebuah pesan dan kemudian b diinisialisasi dengan a*4 atau 12. Kemudian main() dipanggil, yang memanggil metode(), yang melewatkan 42 kepada x.

Di luar kelas dimana ia didefinisikan, metode dan variabel static dapat dipakai secara bebas, terlepas dari objek apapun. Untuk melakukannya, Anda hanya perlu menyebutkan nama kelasnya yang diikuti dengan operator dot. Sebagai contoh, jika Anda ingin memanggil sebuah metode static dari luar kelasnya, Anda dapat melakukannya menggunakan bentuk umum berikut:

namakelas.metode()

Di sini, namakelas adalah nama kelas di mana metode static dideklarasikan. Seperti yang dapat Anda lihat, format sama dengan yang digunakan untuk memanggil metode-metode tak statis melalui variabel referensi objek. Variabel static dapat diakses dengan cara yang sama, menggunakan operator dot pada nama kelas. Inilah bagaimana Java mengimplementasikan versi terkendali dari metode dan variabel global.

Berikut adalah sebuah contoh yang mengilustrasikan konsep ini. Di dalam main(), metode static dengan nama panggilAku() dan variabel static, b, diakses melalui nama kelasnya DemoStatik:

class DemoStatik {
   static int a = 42;
   static int b = 99;

   static void panggilAku() {
      System.out.println("a = " + a);
   }
}

public class GunakanStatik2 {
   public static void main(String args[]) {
	   DemoStatik.panggilAku();
		
      System.out.println("b = " + DemoStatik.b);
   }
}

Ketika dijalankan, program ini menghasilkan keluaran berikut:

a = 42
b = 99


Mengenalkan final
Anggota data kelas dapat dideklarasikan final. Dengan melakukannya, nilai dari anggota data kelas tersebut tidak dapat dimodifikasi pada saat program dieksekusi. Anda dapat melakukannya dengan dua cara: Pertama, Anda memberikannya sebuah nilai ketika dideklarasikan. Kedua, Anda dapat menugaskannya sebuah nilai menggunakan konstruktor. Pendekatan pertama yang paling umum dilakukan. Berikut adalah beberapa contohnya:

final int FILE_NEW = 1;
final int FILE_OPEN = 2;
final int FILE_SAVE = 3;
final int FILE_SAVEAS = 4;
final int FILE_QUIT = 5;


Array dan Kelas
Array telah dikenalnya di awal buku ini, sebelum kelas didiskusikan. Sekarang setelah Anda mengetahui tentang kelas, Anda perlu mengetahui hal penting tentang array: array diimplementasikan sebagai objek. Karenanya, ada keuntungan yang bisa Anda dapatkan dari array: Anda bisa mendapatkan panjang array dengan mengakses variabel kelas length. Semua array memiliki variabel ini. Berikut adalah sebuah program yang mendemonstrasikannya:

// Program ini mendemonstrasikan anggota data length dari array.
public class PanjangArray {
   public static void main(String args[]) {
      int a1[] = new int[10];
      int a2[] = {3, 5, 7, 1, 8, 99, 44, -10};
      int a3[] = {4, 3, 2, 1};
		
      System.out.println("Panjang dari a1 = " + a1.length);
      System.out.println("Panjang dari a2 = " + a2.length);
      System.out.println("Panjang dari a3 = " + a3.length);
   }
}

Ketika dijalankan, program ini menghasilkan keluaran:

Panjang dari a1 = 10
Panjang dari a2 = 8
Panjang dari a3 = 4

Seperti yang dapat Anda lihat, ukuran array ditampilkan. Ingat bahwa nilai dari length tidak ada kaitannya dengan banyak elemen array yang digunakan. Variabel tersebut hanya merefleksikan banyak elemen yang dapat dimuat oleh array.

Anda dapat memanfaatkan anggota length pada banyak pekerjaan. Misalnya, di sini diberikan versi terperbaiki dari kelas Tumpukan. Seperti yang Anda ingat, versi sebelumnya dari kelas ini selalu menciptakan tumpukan sepuluh-elemen. Versi berikut mengijinkan Anda untuk menciptakan tumpukan dengan ukuran berapapun. Nilai dari tumpuk.length dipakai untuk mencegah tumpukan melebihi ukurannya.

/* Sekarang, baik tumpuk maupun nitem dideklarasikan private.
 * Ini berarti bahwa keduanya tidak bisa diubah dari luar kelas
 */
class Tumpukan {
   private int tumpuk[];
   private int nitem;

   // Mengalokasikan dan menginisialisasi tumpukan
   Tumpukan(int ukuran) {
      tumpuk = new int[ukuran];
      nitem = -1;
   }

   // Menempatkan item ke atas tumpukan
   void push(int item) {
      if(nitem==tumpuk.length-1) //menggunakan anggota length
         System.out.println("Tumpukan penuh.");
      else
    	  tumpuk[++nitem] = item;
   }
   
   // Mengambil item dari tumpukan
   int pop() {
      if(nitem < 0) {
         System.out.println("Tumpukan kosong.");
         return 0;
      }
      else
         return tumpuk[nitem--];
   }
}

public class UjiTumpukan3 {
   public static void main(String args[]) {
      Tumpukan tumpukan1 = new Tumpukan(5);
      Tumpukan tumpukan2 = new Tumpukan(8);
		
      // menempatkan sejumlah nilai ke atas tumpukan
      for(int i=0; i<5; i++) tumpukan1.push(i);
      for(int i=0; i<8; i++) tumpukan2.push(i);
		
      // mengambil nilai-nilai dari tumpukan
      System.out.println("Tumpukan pada tumpukan1:");
      for(int i=0; i<5; i++)
         System.out.println(tumpukan1.pop());
		
      System.out.println("Tumpukan pada tumpukan2:");
      for(int i=0; i<8; i++)
         System.out.println(tumpukan2.pop());
   }
}

Ketika dijalankan, program ini memberikan keluaran berikut:

Tumpukan pada tumpukan1:
4
3
2
1
0
Tumpukan pada tumpukan2:
7
6
5
4
3
2
1
0


Kelas Bersarang
Anda dimungkinkan untuk mendefinisikan sebuah kelas di dalam kelas lain; kelas semacam itu disebut kelas bersarang. Skop dari sebuah kelas bersarang dibatasi oleh skop dari kelas pembungkusnya atau pengapitnya. Jadi, jika kelas B didefinisikan di dalam kelas A, maka B tidak bebas dari A. Kelas bersarang memilik akses terhadap anggota-anggota, termasuk anggota private, dari kelas pembungkusnya. Namun, kelas pembungkus tidak memiliki akses terhadap anggota-anggota dari kelas bersarang.

Ada dua jenis kelas bersarang: static dan non-static. Kelas bersarang static adalah kelas yang memiliki pemodifikasi akses static. Karena wataknya statis, kelas tersebut harus mengakses anggota-anggota tak-statis dari kelas pembungkusnya melalui sebuah objek. Jadi, kelas itu tidak bisa mengakses anggota-anggota tak-statis dari kelas pembungkusnya secara langsung. Karena pembatasan ini, kelas bersarang statis jarang digunakan.

Jenis yang paling penting dari kelas bersarang adalah kelas inner. Kelas inner adalah kelas bersarang tak-statis. Kelas ini memiliki akses secara langsung ke semua variabel dan metode dari kelas pembungkusnya.

Program berikut mengilustrasikan bagaimana mendefinisikan sebuah kelas inner. Kelas dengan nama Outer memiliki satu variabel kelas bernama outer_x, satu metode kelas dengan nama test(), dan mendefinisikan satu kelas inner dengan nama Inner.

// Demonstrasi kelas inner
class Outer {
   int outer_x = 100;

   void test() {
      Inner inner = new Inner();
      inner.tampil();
   }
   
   // ini adalah sebuah kelas inner
   class Inner {
      void tampil() {
         System.out.println("tampil: outer_x = " + outer_x);
      }
   }
}

public class DemoKelasInner {
   public static void main(String args[]) {
      Outer outer = new Outer();
      outer.test();
   }
}

Ketika dijalankan, program ini memberikan keluaran berikut:

tampil: outer_x = 100

Pada program, sebuah kelas inner dengan nama Inner didefinisikan di dalam skop kelas Outer. Oleh karena itu, sembarang kode pada kelas Inner dapat mengakses secara langsung variabel outer_x. Sebuah metode kelas dengan nama tampil() didefinisikan di dalam Inner. Metode ini menampilkan outer_x. Metode main() dari DemoKelasInner menciptakan sebuah objek dari kelas Outer dan memanggil metode test(). Metode itu menciptakan sebuah objek dari kelas Inner dan memangil metode tampil().

Adalah penting untuk menyadari bahwa objek dari Inner hanya dapat diciptakan di dalam kelas Outer. Kompilator Java akan memberikan pesan error jika hal itu tidak dilanggar. Seperti dijelaskan, kelas inner dapat mengakses semua anggota dari kelas pembungkusnya, tetapi kebalikannya tidak berlaku. Anggota dari kelas inner hanya dikenal di dalam skop kelas inner dan tidak bisa dipakai oleh kelas pembungkusnya. Sebagai contoh,

// Program ini tidak akan bisa dikompilasi.
class Outer {
   int outer_x = 100;

   void test() {
      Inner inner = new Inner();
      inner.tampil();
   }

   // ini adalah sebuah kelas inner
   class Inner {
      int y = 10; // y hanya dikenali di dalam Inner

      void tampil() {
         System.out.println("tampil: outer_x = " + outer_x);
      }
   }
   
   void tampily() {
      System.out.println(y); // error, y tidak dikenali di sini
   }
}

public class DemoKelasInner2 {
   public static void main(String args[]) {
      Outer outer = new Outer();
      outer.test();
   }
}


Di sini, y dideklarasikan sebagai variabel kelas Inner. Jadi, ia tidak dikenali di luar kelas itu dan tidak dapat digunakan oleh metode tampily().

Anda juga dimungkinkan mendefinisikan kelas inner di dalam sembarang blok kode. Sebagai contoh, Anda dapat mendefinisikan sebuah kelas bersarang di dalam blok yang didefinisikan oleh sebuah metode atau bahkan di dalam tubuh loop for, seperti pada contoh berikut:

// Mendefinisikan kelas inner di dalam loop for.
class Outer {
   int outer_x = 100;

   void test() {
      for(int i=0; i<10; i++) {
         class Inner {
            void tampil() {
               System.out.println("tampil: outer_x = " + outer_x);
            }
         }

         Inner inner = new Inner();
         inner.tampil();
      }
   }
}

public class DemoKelasInner3 {
   public static void main(String args[]) {
      Outer outer = new Outer();
      outer.test();
   }
}

Jika dijalankan, program ini menghasilkan keluaran berikut:


tampil: outer_x = 100
tampil: outer_x = 100
tampil: outer_x = 100
tampil: outer_x = 100
tampil: outer_x = 100
tampil: outer_x = 100
tampil: outer_x = 100
tampil: outer_x = 100
tampil: outer_x = 100
tampil: outer_x = 100






No comments: