Saturday, December 24, 2016

Bab 5. Pemrograman C# Belajar Dari Contoh


5. Pengenalan Kelas dan Objek







Bab ini akan mengenalkan kelas. Kelas merupakan fondasi bagi C# karena mendefinisikan sifat sebuah objek. Di samping itu, kelas juga membentuk basis untuk pemrograman berorientasi objek. Di dalam suatu kelas didefinisikan kode dan data. Karena kelas dan objek merupakan hal fundamental bagi C#, maka akan dibahas secara panjang lebar, pada beberapa bab dalam buku ini. Bab ini memulai diskusi tentang beberapa fitur utama kelas.


Hal Fundamental Pada Kelas
Anda telah menggunakan beberapa kelas di awal buku ini. Tentu saja, hanya beberapa kelas sederhan yang digunakan, dan belum mengeksploitasi semua fitur yang dimiliki sebuah kelas.

Pada bab ini akan dibahas beberapa fitur utama kelas. Kelas merupakan sebuah template yang mendefinisikan format suatu objek. Kelas menspesifikasi data dan kode yang akan dioperasikan terhadap data tersebut. C# menggunakan spesifikasi kelas untuk membentuk objek. Objek adalah instans dari suatu kelas. Jadi, kelas secara esensial adalah rancangan yang menspesifikasi bagaimana membangun sebuah objek. Adalah hal penting bagi Anda untuk memahami ini: Kelas adalah sebuah abstraksi logis. Representasi fisik dari sebuah kelas tidak ada di dalam memori jika objek dari kelas tersebut tidak diciptakan.


Format Umum Kelas
Ketika Anda mendefinisikan suatu kelas, Anda mendeklarasikan data yang dimuatnya dan kode yang dioperasikan pada data tersebut. Kelas sederhana bisa saja memuat hanya kode atau hanya data saja, tetapi hampir semua kelas di dunia aplikasi memuat keduanya.

Dalam peristilahan umum, data dimuat dalam anggota data yang didefinisikan kelas, dan kode dimuat di dalam anggota fungsi. Sebagai contoh, anggota data (yang juga dikenal dengan bidang) mencakung variabel instand dan variabel statik. Fungsi anggota mencakup metode, konstruktor, destruktor, indekser, event, operator, dan properti. Untuk saat ini, diskusi akan dibatasi pada elemen-elemen esensial: variabel instans dan metode. Berikutnya pada bab ini, akan didiskusikan mengenai konstruktor dan destruktor. Yang lain akan dibahas pada beberapa bab selanjutnya.

Sebuah kelas diciptakan menggunakan katakunci class. Berikut adalah bentuk umum dari sebuah definisi class sederhana yang hanya memuat variabel instans dan metode:

class namakelas {
   // mendeklarasikan variabel instans
   akses  tipe  var1;
   akses  tipe  var2;
   // ...
   akses  tipe varN;

   // mendeklarasikan metode
   akses tipe-nilaibalik metode1(parameter-parameter) {
     // tubuh metode
   }

   akses tipe-nilaibalik metode2(parameter-parameter) {
     // tubuh metode
   }
   //...
   akses tipe-nilaibalik metodeN(parameter-parameter) {
     // tubuh metode
   }
}

Perhatikan bahwa setiap deklarasi variabel metode diawali dengan akses. Di sini, akses adalah sebuah penspesifikasi akses, seperti public, yang menspesifikasi bagaimana anggota dapa diakses. Seperti disebutkan pada Bab 1, anggota kelas dapat privat bagi sebuah kelas atau umum bagi lainnya. Penspesifikasi akses menentukan tipe akses yang diijinkan. Penspesifikasi akses bersifat opsional, dan jika tidak diberikan, maka anggoa bersifat privat bagi kelas tersebut. Anggota dengan akses privat hanya dapat dipakai oleh sesama anggota di dalam kelas. Sebagai contoh pada bab ini, semua anggota (kecuali untuk metode Main())dispesifikasi sebagai public, yang berarti bahwa semua anggota tersebut dapat diakses oleh kode lain, bahkan oleh kode yang didefinisikan di luar kelas tersebut. Penspesifikasi akses akan dibahas pada Bab 7.

Sampai titik ini, kelas yang telah digunakan hanya mempunyai satu metode: Main(). Namun, metode Main() hanya diperlukan jika kelas tersebut merupakan titik awal program Anda.


Mendefinisikan Kelas
Untuk mengilustrasikan kelas, akan dikembangkan sebuah kelas yang mencakup informasi mengenai bangunan, seperti rumah, kedai, kantor, dan lainnya. Kelas ini disebut dengan Bangunan, dan menyimpan tiga item informasi tentang sebuah bangungan: jumlah lantai, luas bangunan, dan jumlah penghuni.

Versi pertama dari Bangunan ditunjukkan di sini. Kelas ini mendefinisikan tiga variabel instans: Lantai, Luas, dan Penghuni. Perhatikan bahwa Bangunan tidak memuat sembarang metode. Jadi, hanya memuat data. (Nanti akan ditambahkan metode pada kelas tersebut).

class Bangunan {
  public int Lantai; // jumlah lantai
  public int Luas; // luas bangunan
  public int Penghuni; // jumlah penghuni
}

Variabel instans yang didefinisikan oleh Bangunan mengilustrasikan cara bagaimana variabel instans dideklarasikan secara umum. Bentuk umum pendeklarasian sebuah variabel instans ditunjukkan di sini:

akses tipe nama-var;

Di sini, akses menspesifikasi akses; tipe menspesifikasi tipe variabel; dan nama-var menspesifikasi nama variabel. Jadi, di samping penspesifikasi akses, Anda mendeklarasikan variabel instans seperti layaknya Anda mendeklarasikan variabel lokal. Untuk Bangunan, variabel instans diawali dengan pemodifikasi akses public. Seperti yang telah dijelaskan, ini membolehkannya untuk diakses oleh kode di luara Bangunan.

Definisi class menciptakan sebuah tipe data baru. Pada kasus ini, tipe data baru dinamakan Bangunan. Anda dapat menggunakan nama ini untuk mendeklarasikan objek bertipe Bangunan. Ingat bahwa deklarasi class hanya merupakan sebuah deskripsi tipe; ia tidak menciptakan objek aktual. Jadi, kode sebelumnya tidak menyebabkan penciptaan objek bertipe Bangunan. Untuk menciptakan sebuah objek Bangunan, Anda bisa menggunakan statemen seperti ini:

Bangunan rumah = new Bangunan();  // menciptakan sebuah objek bertipe Bangunan

Setelah statemen ini dieksekusi, rumah akan menjadi instans dari Bangunan. Jadi, ia akan memiliki realitas fisik. Untuk sementara ini, Anda tak perlu khawatir tentang detil statemen ini.

Setiap kali Anda menciptakan instans dari sebuah kelas, Anda menciptakan sebuah objek yang memuat salinan dari setiap variabel instans yang didefinisikan oleh kelas tersebut. Jadi, setiap objek Bangunan akan memuat salinan sendiri dari variabel-variabel instans Lantai, Luas, dan Penghuni. Untuk mengakses ketiga variabel tersebut, Anda dapat memakai operator akses, yang berupa sebuah titik. Operator ini dikenal juga dengan operator dot. Operator dot menghubungkan nama objek dengan nama anggota. Bentuk umum atas operator dot ditunjukkan di sini:

objek.anggota

Jadi, objek dispesifikasi di sisi kiri, dan anggota ditempatkan di sebelah kanan operator dot. Sebagai contoh, untuk menugaskan nilai 2 kepada variabel Lantai dari objek rumah, digunakan statemen berikut:

rumah.Lantai = 2;

Secara umum, Anda dapat menggunakan operator dot untuk mengakses variabel instans dan metode. Berikut adalah sebuah program utuh yang menggunakan kelas Bangunan:

// Sebuah program yang menggunakan kelas Bangunan.
using System;

class Bangunan
{
    public int Lantai; // jumlah lantai
    public int Luas; // luas bangunan
    public int Penghuni; // jumlah penghuni
}

// kelas ini mendeklarasikan sebuah objek bertipe Bangunan.
class DemoBangunan
{
    static void Main()
    {
        Bangunan rumah = new Bangunan(); // menciptakan sebuah objek Bangunan
        int luasPO; // luas per orang
       
        // Menugaskan nilai kepada bidang dalam rumah.
        rumah.Penghuni = 4;
        rumah.Luas = 2500;
        rumah.Lantai = 2;
       
        // Menghitung luas per orang.
        luasPO = rumah.Luas / rumah.Penghuni;
       
        Console.WriteLine("rumah mempunyai:\n " +
                          rumah.Lantai + " lantai\n " +
                          rumah.Penghuni + " penghuni\n " +
                          rumah.Luas + " luas bangunan\n " +
                          luasPO + " luas per orang");
    }
}

Program ini memuat dua kelas: Bangunan dan DemoBangunan. Di dalam DemoBangunan, metode Main() menciptakan sebuah instans dari Bangunan, yang dinamakan rumah. Kemudian kode di dalam Main() mengakses beberapa variabel instans yang berkaitan dengan rumah, menugaskan nilai kepadanya, dan menggunakannya. Penting untuk memahami bahwa Bangunan dan DemoBangunan adalah dua kelas terpisah. Satu-satunya hubungan keduanya adalah bahwa satu kelas menciptakan instans dari kelas lainnya. Meskipun keduanya merupakan kelas terpisah, kode di dalam DemoBangunan dapat mengakses anggota dari Bangunan karena anggota tersebut dideklaraiskan public. Jika tidak diberikan penspesifikasi akses public, maka akses terhadap anggota tersebut hanya terbatas di dalam kelas Bangunan, dan kelas DemoBangunan tidak akan bisa mengaksesnya.

Program tersebut menghasilkan keluaran berikut:

rumah mempunyai:
 2 lantai
 4 penghuni
 2500 luas bangunan
 625 luas per orang

Setiap objek memiliki salinan sendiri atas variabel instans yang didefinisikan kelasnya. Jadi, isi variabel di dalam satu objek bisa berbeda dari isi variabel di dalam objek lain. Tidak ada hubungan antara dua objek kecuali fakta bahwa keduanya merupakan objek bertipe sama. Sebagai contoh, dua objek Bangunan, masing-masing memiliki salinan sendiri dari Lantai, Luas, dan Penghuni, dan isi dari ketiga variabel instans tersebut bisa berbeda di dalam dua objek. Program berikut mendemonstrasikan fakta ini:

// Program ini menciptakan dua objek Bangunan.
using System;

class Bangunan {
  public int Lantai; // jumlah lantai
  public int Luas; // luas bangunan
  public int Penghuni; // jumlah penghuni
}

// kelas ini mendeklarasikan dua objek bertipe Bangunan.
class DemoBangunan {
  static void Main() {
    Bangunan rumah = new Bangunan();
    Bangunan kantor = new Bangunan();
    int luasPO; // luas per orang

    // menugaskan nilai ke bidang dalam rumah.
    rumah.Penghuni = 4;
    rumah.Luas = 2500;
    rumah.Lantai = 2;

    // menugaskan nilai ke bidang dalam kantor.
    kantor.Penghuni = 25;
    kantor.Luas = 4200;
    kantor.Lantai = 3;

    // menghitung luas per orang dalam rumah.
    luasPO = rumah.Luas / rumah.Penghuni;
   
    Console.WriteLine("rumah mempunyai:\n " +
                      rumah.Lantai + " lantai\n " +
                      rumah.Penghuni + " penghuni\n " +
                      rumah.Luas + " luas bangunan\n " +
                      luasPO + " luas per orang");
    Console.WriteLine();

    // menghitung luas per orang dalam kantor.
    luasPO = kantor.Luas / kantor.Penghuni;

    Console.WriteLine("kantor mempunyai:\n " +
                      kantor.Lantai + " lantai\n " +
                      kantor.Penghuni + " penghuni\n " +
                      kantor.Luas + " luas bangunan\n " +
                      luasPO + " luas per orang");
  }
}

Program ini menghasilkan keluaran berikut:

rumah mempunyai:
 2 lantai
 4 penghuni
 2500 luas bangunan
 625 luas per orang

kantor mempunyai:
 3 lantai
 25 penghuni
 4200 luas bangunan
 168 luas per orang

Seperti yang bisa Anda lihat, data rumah sama sekali terpisah dari data yang dimuat kantor. Gambar 5.1 mengilustrasikan situasi ini.


Gambar 5.1 Variabel instans suatu objek berbeda dengan variabel instans objek lain


Bagaimana Objek Diciptakan
Pada program sebelumnya, baris berikut dipakai untuk mendeklarasikan sebuah objek bertipe Bangunan:

Bangunan rumah = new Bangunan();

Deklarasi ini melakukan tiga fungsi: Pertama, ia mendeklarasikan sebuah variabel bernama rumah bertipe Bangunan. Variabel ini sendiri bukan sebuah objek, tetapi hanyalah sebuah variabel yang merujuk ke sebuah objek. Kedua, deklarasi ini menciptakan salinan fisik dari objek. Ini dilakukan menggunakan operator new. Terakhir, deklarasi ini menugaskan sebuah referensi yang menunjuk ke objek kepada rumah. Jadi, setelah baris ini dieksekusi, rumah akan menunjuk ke sebuah objek bertipe Bangunan.

Operator new secara dinamis mengalokasikan memori untuk sebuah objek dan menghasilkan nilai balik berupa suatu referensi yang menunjuk ke objek tersebut. Referensi ini kemudian disimpan di dalam variabel. Jadi, dalam C#, semua objek kelas dialokasikan secara dinamis.

Seperti yang Anda harapkan, adalah hal yang memungkinkan untuk memisahkan deklarasi atas rumah dari objek yang akan ditunjuk, seperti ditunjukkan di sini:

Bangunan rumah;  // deklarasi referensi ke objek
rumah = new Bangunan();  // mengalokasikan sebuah objek Bangunan

Baris pertama mendeklarasikan rumah sebagai sebuah referensi yang menunjuk ke suatu objek bertipe Bangunan. Jadi, rumah adalah sebuah variabel yang menunjuk ke suatu objek, bukan merupakan objek itu sendiri. Baris berikutnya menciptakan sebuah objek Bangunan baru dan menugaskan referensi yang menunjuk ke objek tersebut kepada rumah. Sekarang, rumah terhubung dengan sebuah objek.

Fakta bahwa objek kelas diakses melalui referensi menjelaskan mengapa kelas disebut dengan tipe referensi. Perbedaan utama antara tipe nilai dan tipe referensi adalah  apa yang dimaksud dengan tiap tipe. Untuk variabel bertipe nilai, variabel tersebut memuat nilai. Sebagai contoh, diberikan

int x;
x = 10;

x memuat nilai 10 karena x merupakan variabel bertipe int, yang bertipe nilai. Namun, dalam kasus

Bangunan rumah = new Bangunan();

rumah tidak memuat objek, tetapi memuat sebuah referensi yang menunjuk ke objek Bangunan.


Variabel Referensi dan Penugasan
Dalam operasi penugasan, variabel referensi berperan berbeda dari variabel bertipe nilai, seperti int. Ketika Anda menugaskan satu variabel bertipe nilai kepada variabel lain, situasinya menjadi sederhana. Variabel di sisi kiri operator penugasan menerima salinan nilai dari variabel di sisi kanan operator. Ketika Anda menugaskan satu objek bertipe referensi kepada variabel bertipe referensi lain, situasi menjadi sedikit lebih kompleks karena penugasan menyebabkan variabel referensi di sisi kiri operator penugasan  menunjuk ke objek yang ditunjuk oleh variabel referensi di sisi kanan operator penugasan. Objek itu sendiri tidak disalin. Sebagai contoh, perhatikan fragmen berikut:

Bangunan rumah1 = new Bangunan();
Bangunan rumah2 = rumah1;

Pada pandangan pertama, adalah hal mudah untuk berpikir bahwa rumah1 dan rumah2 menunjuk ke dua objek terpisah, tetapi pemikiran ini menyesatkan. Kenyataannya adalah bahwa rumah1 dan rumah2 keduanya menunjuk ke objek yang sama. Penugasan rumah1 kepada rumah2 hanya membuat rumah2 menunjuk ke objek yang ditunjuk oleh rumah1. Setelah penugasan

rumah1.Luas = 2600;

dieksekusi, kedua statemen WriteLine()

Console.WriteLine(rumah1.Luas);
Console.WriteLine(rumah2.Luas);

menampilkan nilai sama: 2600.

Meskipun rumah1 dan rumah2 keduanya menunjuk ke objek yang sama. Tetapi, perhatikan contoh berikut:

Bangunan rumah1 = new Bangunan();
Bangunan rumah2 = rumah1;  //rumah 1 dan rumah2 menunjuk ke objek yang sama
Bangunan rumah3 = new Bangunan();
rumah2 = rumah3  //sekarang, rumah2 dan rumah3 menunjuk ke objek yang sama

Setelah runtun statemen tersebut dieksekusi, rumah2 menunjuk ke objek yang ditunjuk oleh rumah3. Objek yang ditunjuk oleh rumah1 tidak berubah.


Metode
Seperti yang telah dijelaskan, variabel instans dan metode merupakan konstituen utama suatu kelas. Sejauh ini, kelas Bangunan hanya memuat data, tidak ada metode. Meskipun kelas Bangunan ini dapat diterima, namun kebanyakan kelas memuat metode. Metode merupakan subrutin yang memanipulasi data yang didefinisikan kelas, dan, pada banyak kasus, menyediakan akses terhadap data tersebut. Secara umum, bagian lain dari suatu program akan berinteraksi dengan sebuah kelas melalui metodenya.

Sebuah metode memuat satu atau lebih statemen. Dalam kode C# yang ditulis secara profesional, setiap metode hanya melakukan satu tugas. Setiap metode mempunya nama, dan nama itu digunakan untuk memanggil metode. Secara umum, Anda dapat menamai metode menggunakan sembarang pengenal valid yang Anda inginkan. Namun, ingat bahwa Main() hanya diperuntukkan bagi metode yang mengawali eksekusi program. Di samping itu, Anda dilarang menggunakan katakunci C# sebagai nama metode.

Ketika menandai metode di dalam teks, metode memiliki sepasang kurung yang ditempatkan setelah nama metode. Sebagai contoh, jika nama metode adalah DapatNil, maka ia ditulis DapatNil() ketika namanya digunakan di dalam kalimat. Notasi ini membantu Anda untuk membedakan nama variabel dari nama metode dalam buku ini.

Bentuk umum atas sebuah metode ditampilkan di sini:

akses tipe-nilaibalik  nama (daftar-parameter) {
   // tubuh metode
}

Di sini, akses adalah pemodifikasi akses yang mengatur bagian program yang dapat memanggil metode tersebut. Seperti dijelaskan sebelumnya, pemodifikasi akses bersifat opsiona. Jika tidak diberikan, maka metode bersifat privat bagi kelas. Untuk sekarang, metode dideklarasikan sebagai public sehingga dapat dipanggil oleh sembarang kode lain di dalam program. tipe-nilaibalik menspesifikasi tipe data yang dijadikan nilai balik oleh metode. Tipe nilai balik bisa berupa sembarang tipe sah, termasuk tipe kelas yang Anda ciptakan. Jika metode tidak menghasilkan nilai balik, tipenya harus void. nama menspesifikasi nama metode, yang dapat berupa pengenal sah. daftar-parameter merupakan sederet pasangan tipe dan pengenal yang dipisahkan dengan koma. Parameter adalah variabel yang menerima nilai dari argumen yang dilewatkan kepada metode ketika metode tersebut dipanggil. Jika metode tidak memiliki parameter, maka daftar parameternya dibiarkan kosong.


Menambahkan Metode Dalam Kelas Bangunan
Seperti yang telah dijelaskan, metode suatu kelas secara umum memanipulasi dan menyediakan akses terhadap data kelas. Dengan pemahaman ini, Anda perlu mengingat bahwa Main() dalam beberapa contoh sebelumnya menghitung luas per orang dengan membagi luas bangunan dengan jumlah penghuni. Meskipun secara teknis perhitungan ini benar, teknik ini bukanlah cara terbaik dalam menangani perhitungan ini. Perhitungan luas per orang seharusnya ditangai oleh kelas Bangunan itu sendiri. Alasannya adalah agar dapat memahami bahwa luas per orang dari suatu bangunan sangat bergantung pada nilai-nilai di dalam bidang Luas dan Penghuni, yang terenkapsulasi oleh Bangunan. Jadi, sangat memungkinkan bagi kelas Bangunan untuk melakukan kalkulasi ini. Di samping itu, dengan menambahkan perhitungan ini ke dalam Bangunan, Anda mencegah setiap program yang menggunakan Bangunan dari penghitungan secara manual. Ini mencegah duplikasi kode yang tak penting. Terakhir, dengan menambahkan sebuah metode untuk menghitung luas per orang ke dalam kelas Bangunan, Anda  telah melakukan pemrograman berorientasi objek dengan mengenkapsulasi kuantitas yang berelasi langsung dengan Bangunan.

Untuk menambahkan sebuah metode ke dalam Bangunan, Anda perlu menspesifikasinya di dalam deklarasi Bangunan. Sebagai contoh, versi  Bangunan berikut memuat sebuah metode bernama LuasPerOrang() yang menampilkan luas per orang dari suatu bangunan:

// Program ini menciptakan dua objek Bangunan.
using System;

class Bangunan {
  public int Lantai; // jumlah lantai
  public int Luas; // luas bangunan
  public int Penghuni; // jumlah penghuni

  // Menampilkan luas per orang.
  public void LuasPerOrang() {
    Console.WriteLine(" " + Luas / Penghuni + " luas per orang");
  }
}

// menggunakan metode LuasPerOrang().
class DemoBangunan {
  static void Main() {
    Bangunan rumah = new Bangunan();
    Bangunan kantor = new Bangunan();
    int luasPO; // luas per orang

    // menugaskan nilai ke bidang dalam rumah.
    rumah.Penghuni = 4;
    rumah.Luas = 2500;
    rumah.Lantai = 2;

    // menugaskan nilai ke bidang dalam kantor.
    kantor.Penghuni = 25;
    kantor.Luas = 4200;
    kantor.Lantai = 3;

    Console.WriteLine("rumah mempunyai:\n " +
                      rumah.Lantai + " lantai\n " +
                      rumah.Penghuni + " penghuni\n " +
                      rumah.Luas + " luas bangunan");
    rumah.LuasPerOrang();
     
    Console.WriteLine();

    Console.WriteLine("kantor mempunyai:\n " +
                      kantor.Lantai + " lantai\n " +
                      kantor.Penghuni + " penghuni\n " +
                      kantor.Luas + " luas bangunan");
    kantor.LuasPerOrang();
  }
}

Keluaran program ditunjukkan di sini:

rumah mempunyai:
 2 lantai
 4 penghuni
 2500 luas bangunan
 625 luas per orang

kantor mempunyai:
 3 lantai
 25 penghuni
 4200 luas bangunan
 168 luas per orang

Akan diperiksa beberapa elemen kunci pada program ini, dimulai dengan metode LuasPerOrang(). Baris pertama dari LuasPerOrang() adalah

public void LuasPerOrang() {

Baris ini mendeklarasikan sebuah metode bernama LuasPerOrang() yang tidak memiliki parameter. Pendeklarasian ini dispesifikasi sebagai public, sehingga dapat dipakai oleh bagian lain dari program. Tipe nilai balik metode ini adalah void. Jadi, LuasPerOrang() tidak menghasilkan nilai balik apapun kepada pemanggil. Baris ini diakhiri dengan kurung kurawal buka untuk mengapit tubuh metode.

Tubuh metode LuasPerOrang() hanya memuat statemen ini:

Console.WriteLine(" " + Luas / Penghuni + " luas per orang");

Statemen ini menampilkan luas per orang dari suatu bangunan dengan membagi Luas oleh Penghuni. Karena setiap objek yang bertipe Bangunan mempunyai salinan sendiri atas Luas dan Penghuni, ketika LuasPerOrang() dipanggil, penghitungan melibatkan salinan kedua variabel tersebut dari objek pemanggil.

Metode LuasPerOrang() diakhiri dengan kurung kurawal tutup. Ini menyebabkan kendali program dialihkan kepada pemanggil.

Berikutnya, akan ditengok baris kode berikut di dalam Main():

rumah.LuasPerOrang();

Statemen ini memanggil metode LuasPerOrang() pada rumah. Yaitu, ia memanggil LuasPerOrang() agar diterapkan pada objek yang ditunjuk oleh rumah, dengan menggunakan operator dot. Ketika sebuah metode dipanggil, kendali program dialihkan ke metode tersebut. Ketika metode berhenti, kendali dialihkan kembali kepada pemanggil.

Pada kasus ini, pemanggilan terhadap rumah.LuasPerOrang() akan menampilkan luas per orang dari suatu bangunan yang didefinisikan oleh rumah. Dengan pengertian sama, pemanggilan terhadap kantor.LuasPerOrang() akan menampilkan luas per orang dari suatu bangunan yang didefinisikan oleh kantor. Setiap kali LuasPerOrang() dipanggil, ia menampilkan luar per orang dari objek yang dispesifikasi.

Ada hal yang sangat penting untuk diperhatikan dalam metode LuasPerOrang(): Variabel instans Luas dan Penghuni dirujuk secara langsung, tanpa penggunaan operator dot. Ketika metode menggunakan variabel instans yang didefinisikan oleh kelasnya, metode itu secara langsung melakukannya, tanpa mereferensi secara eksplisit ke objek dan tanpa menggunakan operator dot.


Kembali dari Metode
Secara umum, ada dua kondisi yang menyebabkan hal ini. Pertama, seperti metode LuasPerOrang() pada contoh sebelumnya, yaitu ketika kurung kurawal tutup dijumpai. Kedua ketika statemen return dieksekusi. Ada dua format return: Satu untuk digunakan dalam metode void (yang tidak menghasilkan nilai balik) dan satu lagi untuk metode yang menghasilkan nilai balik. Format pertama akan didiskusikan di sini. Bagian selanjutnya akan menjelaskan bagaimana menghasilkan nilai balik.

Dalam metode void, Anda dapat menyebabkan penghentian segera dari sebuah metode menggunakan format return seperti ini:

return ;

Ketika statemen ini dieksekusi, kendali program kembali ke pemanggil, melompati sisa kode di dalam metode. Sebagai contoh, perhatikan metode ini:

public void MetodeKu() {
  int i;

  for(i=0; i<10; i++) {
    if(i == 5) return; // berhenti pada 5
      Console.WriteLine();
  }
}

Di sini, loop for hanya beriterasi dari 0 sampai 5, karena begitu i sama dengan 5, metode akan kembali kepada pemanggil. Kepemilikan lebih dari satu statemen return diijinkan dalam sebuah metode, khususnya ketika terdapat dua atau lebih rute. Sebagai contoh,

public void MetodeKu() {
  // ...
  if(selesai) return;
  // ...
  if(error) return;
}


Mengembalikan Sebuah Nilai
Metode tanpa nilai balik jarang dijumpai, dan kebanyakan metode menghasilkan nilai balik. Pada kenyataannya, kemampuan untuk menghasilkan nilai balik adalah fitur paling penting yang dimiliki suatu metode. Anda telah melihat sebuah contoh nilai balik dari fungsi Math.Sqrt() pada Bab 2 untuk mendapatkan akar kuadrat atas suatu nilai.

Nilai balik dipakai untuk berbagai kepentingan dalam pemrograman. Pada beberapa kasus, seperti pada Math.Sqrt(), nilai balik memuat keluaran dari perhitungan. Pada kasus lain, nilai balik hanya dipakai untuk mengindikasikan kegagalan atau keberhasilan. Apapun tujuannya, penggunaan nilai balik dari suatu metode merupakan bagian penting dalam pemrograman C#.

Metode menghasilkan nilai balik dengan memanggil rutin menggunakan format return ini:

return nilai;

Di sini, nilai adalah nilai balik.

Anda dapat menggunakan nilai balik untuk memperbaiki implementasi dari LuasPerOrang(). Daripada hanya menampilkan luas per orang dari suatu bangunan, pendekatan lebih baik yang bisa dilakukan adalah meminta LuasPerOrang() untuk menghasilkan nilai balik. Keuntungan dari pendekatan ini adalah Anda dapat memakai nilai balik untuk kepentingan lain. Contoh berikut memodifikasi LuasPerOrang() untuk menghasilkan nilai balik berupa luas per orang dari suatu bangunan.

// Menghasilkan nilai balik dari metode LuasPerOrang().
using System;

class Bangunan {
  public int Lantai; // jumlah lantai
  public int Luas; // luas bangunan
  public int Penghuni; // jumlah penghuni

  // Menampilkan luas per orang.
  public int LuasPerOrang() {
    return Luas / Penghuni;
  }
}

// menggunakan nilai balik dari LuasPerOrang().
class DemoBangunan {
  static void Main() {
    Bangunan rumah = new Bangunan();
    Bangunan kantor = new Bangunan();
    int luasPO; // luas per orang

    // menugaskan nilai ke bidang dalam rumah.
    rumah.Penghuni = 4;
    rumah.Luas = 2500;
    rumah.Lantai = 2;

    // menugaskan nilai ke bidang dalam kantor.
    kantor.Penghuni = 25;
    kantor.Luas = 4200;
    kantor.Lantai = 3;

    // mendapatkan luas per orang untuk rumah
    luasPO = rumah.LuasPerOrang();

    Console.WriteLine("rumah mempunyai:\n " +
                      rumah.Lantai + " lantai\n " +
                      rumah.Penghuni + " penghuni\n " +
                      rumah.Luas + " luas bangunan\n " +
                      luasPO + " luas per orang");
         
    Console.WriteLine();

    // mendapatkan luas per orang untuk kantor
    luasPO = kantor.LuasPerOrang();

    Console.WriteLine("kantor mempunyai:\n " +
                      kantor.Lantai + " lantai\n " +
                      kantor.Penghuni + " penghuni\n " +
                      kantor.Luas + " luas bangunan\n " +
                      luasPO + " luas per orang");
  }
}

Keluaran program sama dengan yang ditampilkan sebelumnya. Pada program, perhatikan bahwa ketika metode LuasPerOrang() dipanggil, ia ditempatkan di sisi kanan operator penugasan. Di sisi kiri operator penugasan adalah variabel yang akan menerima yang dijadikan nilai balik oleh LuasPerOrang(). Jadi, setelah

luasPO = rumah.LuasPerOrang();

dieksekusi, luas per orang dari objek rumah disimpan di dalam luasPO. Perhatikan bahwa LuasPerOrang() sekarang mempunyai nilai balik bertipe int. Ini berarti bahwa ia akan mengembalikan sebuah nilai integer kepada pemanggil. Tipe nilai balik suatu metode penting karena tipe data yang dikembalikan oleh metode harus kompatibel dengan tipe nilai balik yang dispesifikasi oleh metode. Jadi, jika Anda menginginkan sebuah metode untuk mengembalikan data bertipe double, maka tipe nilai baliknya harus bertipe double.

Meskipun, program sebelumnya benar, tetapi tidak ditulis seefisien mungkin. Pada kenyataannya, tidak diperlukan variabel luasPO. Pemanggilan terhadap LuasPerOrang() dapat dipakai di dalam statemen WriteLine() secara langsung, seperti ditunjukkan di sini:

Console.WriteLine("rumah mempunyai:\n " +
                      rumah.Lantai + " lantai\n " +
                      rumah.Penghuni + " penghuni\n " +
                      rumah.Luas + " luas bangunan\n " +
                      rumah. LuasPerOrang() + " luas per orang");

Pada kasus ini, ketika WriteLine() dieksekusi, rumah.LuasPerOrang() akan dipanggil secara otomatis, dan nilai baliknya dilewatkan kepada WriteLine(). Di samping itu, Anda dapat memakai pemanggilan terhadap LuasPerOrang() dimanapun luas per orang dari sebuah objek Bangunan diperlukan. Sebagai contoh, statemen ini membandingkan luas per orang atas dua bangunan:

if(b1.LuasPerOrang() > b2. LuasPerOrang ())
  Console.WriteLine("b1 mempunyai luas lebih besar untuk setiap orang");


Menggunakan Parameter
Adalah memungkinkan untuk melewatkan satu atau lebih nilai kepada sebuah metode ketika metode itu dipanggil. Nilai yang dilewatkan kepada metode disebut dengan argumen. Di dalam metode, variabel yang menerima argumen disebut dengan parameter formal, atau hanya parameter. Parameter dideklarasikan dan diapit sepasang kurung yang ditempatkan setelah nama metode. Sintaks deklarasi parameter sama dengan deklarasi variabel. Skop suatu parameter adalah tubuh metodenya.
Berikut adalah contoh sederhana yang menggunakan parameter. Di dalam kelas PeriksaAngka, metode apaPrima() menghasilkan true jika nilai yang dilewatkan adalah prima. Sebaliknya, dihasilkan nilai balik false. Oleh karena itu, apaPrima() mempunyai tipe nilai balik bool.

// Contoh sederhana yang menggunakan parameter.
using System;

class PeriksaAngka {
  // Menghasilkan true jika x prima.
  public bool apaPrima(int x) {
    if(x <= 1) return false;

    for(int i=2; i <= x/i; i++)
      if((x %i) == 0) return false;
   
    return true;
  }
}

class DemoParameter {
  static void Main() {
      PeriksaAngka ob = new PeriksaAngka();
   
    for(int i=2; i < 10; i++)
      if(ob.apaPrima(i)) Console.WriteLine(i + " prima.");
      else Console.WriteLine(i + " bukan prima.");
  }
}

Berikut adalah keluaran yang dihasilkan program:

2 prima.
3 prima.
4 bukan prima.
5 prima.
6 bukan prima.
7 prima.
8 bukan prima.
9 bukan prima.

Di dalam program, apaPrima() dipanggil delapan kali, dan setiap kali dipanggil, nilai berbeda dilewatkan. Akan diperiksa proses ini lebih dekat lagi. Pertama, perhatikan bagaimana apaPrima() dipanggil. Argumen dispesifikasi di antara sepasang kurung. Ketika apaPrima() dipanggil pertama kali, kepadanya dilewatkan nilai 2. Jadi, ketika apaPrima() mulai dieksekusi, parameter x menerima nilai 2. Pada pemanggilan kedua, argumennya adalah 3, dan x kemudian mempunyai nilai 3. Pada pemanggilan ketiga, argumennya adalah 4, yang merupakan nilai yang diterima x, dan seterusnya.

Metode dapat mempunyai lebih dari satu parameter. Anda hanya perlu mendeklarasikan setiap parameter, dipisahkan dengan koma. Sebagai contoh, di sini kelas PeriksaAngka diekspansi dengan menambahkan sebuah metode yang bernama FaktorTerkecilBersama(), yang menghasilkan nilai balik berupa faktor kecil bersama dari kedua argumennya.


// Menambahkan sebuah metode yang mengambil dua argumen.
using System;

class PeriksaAngka {
  // Menghasilkan true jika x prima.
  public bool apaPrima(int x) {
    if(x <= 1) return false;

    for(int i=2; i <= x/i; i++)
      if((x %i) == 0) return false;
   
    return true;
  }

  // Menghasilkan faktor terkecil bersama.
  public int FaktorTerkecilBersama(int a, int b) {
    int maks;

    if(apaPrima(a) || apaPrima(b)) return 1;

    maks = a < b ? a : b;

    for(int i=2; i <= maks/2; i++)
      if(((a%i) == 0) && ((b%i) == 0)) return i;

    return 1;
  }
}

class DemoParameter
{
    static void Main()
    {
        PeriksaAngka ob = new PeriksaAngka();
        int a, b;
       
        for (int i = 2; i < 10; i++)
            if (ob.apaPrima(i)) Console.WriteLine(i + " prima.");
            else Console.WriteLine(i + " bukan prima.");
       
        a = 7;
        b = 8;
        Console.WriteLine("Faktor terkecil bersama untuk " +
                          a + " dan " + b + " adalah " +
                          ob.FaktorTerkecilBersama(a, b));
       
        a = 100;
        b = 8;
        Console.WriteLine("Faktor terkecil bersama untuk " +
                          a + " dan " + b + " adalah " +
                          ob.FaktorTerkecilBersama(a, b));
       
        a = 100;
        b = 75;
        Console.WriteLine("Faktor terkecil bersama untuk " +
                          a + " dan " + b + " adalah " +
                          ob.FaktorTerkecilBersama(a, b));
    }
}

Perhatikan bahwa ketika FaktorTerkecilBersama() dipanggil, argumen-argumen juga dipisahkan dengan koma. Keluaran dari program ditunjukkan di sini:

2 prima.
3 prima.
4 bukan prima.
5 prima.
6 bukan prima.
7 prima.
8 bukan prima.
9 bukan prima.
Faktor terkecil bersama untuk 7 dan 8 adalah 1
Faktor terkecil bersama untuk 100 dan 8 adalah 2
Faktor terkecil bersama untuk 100 dan 75 adalah 5

Ketika menggunakan parameter jamak, setiap parameter menspesifikasi tipenya sendiri, yang bisa berbeda dari lainnya. Sebagai contoh, berikut adalah sah:

int MetodeKu(int a, double b, float c) {
// ...


Menambahkan Metode Terparameterisasi Ke Bangunan
Anda dapat menambahkan sebuah metode terparameterisasi ke dalam kelas Bangunan. Metode yang akan ditambahkan mempunyai kemampuan untuk menghitung jumlah maksimum penghuni untuk sebuah bangunan, bila diasumsikan bahwa setiap penghuni memerlukan luas minimum. Metode baru ini dinamakan MaksPenghuni(), yang ditampilkan di sini:

// Menghasilkan nilai balik berupa jumlah maksimum penghuni jika
// setiap penghuni memerlukan luas minimum yang dispesifikasi.
public int MaksPenghuni(int minLuas) {
  return Luas / minLuas;
}

Ketika MaksPenghuni() dipanggil, parameter minLuas menerima luas minimum yang diperlukan setiap penghuni. Metode ini membagi total luas bangunan dengan nilai tersebut dan memberikan nilai balik. Keseluruhan kelas Bangunan yang mencakup metode MaksPenghuni() ditampilkan di sini:

/* Menambahkan sebuah metode terparameterisasi yang menghitung
   jumlah maksimum penghuni yang menghuni sebuah bangunan
   bila diasumsikan setiap penghuni memerlukan
   luas minimum yang dispesifikasi.
 */

using System;

class Bangunan
{
    public int Lantai; // jumlah lantai
    public int Luas; // luas bangunan
    public int Penghuni; // jumlah penghuni

    // Menampilkan luas per orang.
    public int LuasPerOrang()
    {
        return Luas / Penghuni;
    }

    // Memberikan nilai balik berupa jumlah maksimum penghuni
    // jika setiap penghuni sedikitnya memerlukan luas minimum
    // yang dispesifikasi.
    public int MaksPenghuni(int minLuas)
    {
        return Luas / minLuas;
    }
}

// menggunakan MaksPenghuni().
class DemoBangunan
{
    static void Main()
    {
        Bangunan rumah = new Bangunan();
        Bangunan kantor = new Bangunan();
        int luasPO; // luas per orang

        // menugaskan nilai ke bidang dalam rumah.
        rumah.Penghuni = 4;
        rumah.Luas = 2500;
        rumah.Lantai = 2;

        // menugaskan nilai ke bidang dalam kantor.
        kantor.Penghuni = 25;
        kantor.Luas = 4200;
        kantor.Lantai = 3;

        Console.WriteLine("Penghuni maksimum rumah jika setiap penghuni mempunyai " +
                          30 + " meter persegi: " +
                          rumah.MaksPenghuni(30));

        Console.WriteLine("Penghuni maksimum kantor jika setiap penghuni mempunyai " +
                          30 + " meter persegi: " +
                          kantor.MaksPenghuni(30));
    }
}

Keluaran program ditunjukkan di sini:

Penghuni maksimum rumah jika setiap penghuni mempunyai 30 meter persegi: 83
Penghuni maksimum kantor jika setiap penghuni mempunyai 30 meter persegi: 140


Menghindari Kode Yang Tak Dapat Dieksekusi
Ketika menciptakan metode, Anda harus menghindari situasi dimana terdapat penggalan kode, pada sembarang situasi, yang tak bisa dieksekusi. Kompiler akan menampilkan pesan peringatan jika Anda menciptakan sebuah metode yang memuat kode yang tak dieksekusi:

public void MetodeKu() {
  char a, b;
  // ...

  if(a==b) {
    Console.WriteLine("sama");
    return;
  }
  else {
    Console.WriteLine("tidak sama");
    return;
  }

  Console.WriteLine("ini kode yang tidak bisa dieksekusi");
}

Di sini, metode MetodeKu() akan selalu kembali kepada pemanggil sebelum statemen terakhir WriteLine() dieksekusi. Jika Anda mencoba mengkompilasi metode ini, maka pesan peringatan akan dibangkitkan kompiler.


Konstruktor
Pada beberapa contoh sebelumnya, variabel instans dari tiap objek Bangunan harus ditetapkan secara manual menggunakan runtun statemen, seperti

rumah.Penghuni = 4;
rumah.Luas = 2500;
rumah.Lantai = 2;

Pendekatan semacam ini tidak akan pernah dipakai di dalam kode C# yang ditulis secara profesional. Pendekatan lain untuk melakukan hal ini adalah menggunakan konstruktor.

Konstruktor menginisialisasi objek ketika diciptakan. Konstruktor mempunyai nama sama dengan kelasnya dan secara sintaks sama dengan metode. Namun, konstruktor tidak memiliki nilai balik. Bentuk umum atas sebuah konstruktor ditampilkan di sini:

akses nama-kelas(daftar-param) {
  // kode konstruktor
}

Secara umum, Anda akan menggunakan konstruktor untuk memberikan nilai awal bagi variabel instans yang didefinisikan oleh kelas atau untuk melakukan prosedur awal yang dibutuhkan untuk membentuk objek utuh. Di samping itu, biasanya akses dideklarasikan public karena normalnya dipanggil dari luas kelasnya. daftar-param bisa kosong, atau bisa menspesifikasi satu atau lebih parameter.

Semua kelas mempunyai konstruktor, tak peduli apakah Anda definisikan atau tidak, karena C# secara otomatis menyediakan sebuah konstruktor default yang menyebabkan semua variabel anggota diinisialisasi dengan nilai defaultnya. Untuk tipe nilai, nilai default adalah nol. Untuk tipe bool, nilai defaultnya adalah false. Untuk tipe referensi, nilai defaultnya adalah null. Namun, begitu Anda mendefinisikan konstruktor sendiri, konstruktor default tidak lagi digunakan. Berikut adalah contoh sederhana yang menggunakan sebuah konstruktor.

// Konstruktor sederhana.
using System;

class KelasKu {
    public int x;
   
    public KelasKu() {
        x = 10;
    }
}

class DemoKonst {
    static void Main() {
        KelasKu t1 = new KelasKu();
        KelasKu t2 = new KelasKu();
       
        Console.WriteLine(t1.x + " " + t2.x);
    }
}

Pada contoh ini, konstruktor untuk KelasKu adalah

public KelasKu() {
        x = 10;
}

Perhatikan bahwa konstruktor dispesifikasi sebagai public. Ini karena konstruktor akan dipanggil dari kode yang didefinisikan dari luar kelasnya. Konstruktor ini menugaskan nilai 10 kepada variabel instans x dari KelasKu. Konstruktor ini dipanggil oleh new ketika sebuah objek diciptakan. Sebagai contoh, pada baris

KelasKu t1 = new KelasKu();

konstruktor KelasKu() dipanggil pada objek t1, memberikan nilai 10 kepada t1.x. Hal ini berlaku juga untuk objek t2. Setelah konstruksi, t2.x memiliki nilai 10. Jadi, keluaran program adalah

10 10


Konstruktor Terparameterisasi
Pada contoh sebelumnya, konstruktor tanpa parameter digunakan. Hal ini berguna pada beberapa situasi, tetapi pada banyak kesempatan Anda memerlukan konstruktor yang mempunyai satu atau lebih parameter. Parameter dicantumkan dalam sebuah konstruktor dengan cara yang sama dengan pencantuman parameter pada sebuah metode, yaitu Anda hanya perlu mendeklarasikannya di dalam kurung setelah nama konstruktor. Sebagai contoh, pada KelasKu di sini diberikan sebuah konstruktor terparameterisasi:

// Konstruktor sederhana.
using System;

class KelasKu {
    public int x;
   
    public KelasKu(int i)
    {
        x = i;
    }
}

class DemoKonst {
    static void Main() {
        KelasKu t1 = new KelasKu(10);
        KelasKu t2 = new KelasKu(88);
        
        Console.WriteLine(t1.x + " " + t2.x);
    }
}

Keluaran program adalah

10  88

Pada versi program ini, konstruktor KelasKu() mendefinisikan satu parameter i, yang dipakai untuk menginisialisasi variabel instans x. Jadi, ketika baris

KelasKu t1 = new KelasKu(10);

dieksekusi, nilai 10 dilewatkan kepada i, yang kemudian ditugaskan kepada x.


Menambahkan Konstruktor Ke Dalam Kelas Bangunan
Anda bisa memperbaiki kelas Bangunan dengan menambahkan sebuah konstruktor yang secara otomatis menginisialisasi bidang Lantai, Luas, dan Penghuni ketika suatu objek dikonstruksi. Perhatikan secara khusus bagaimana objek-objek Bangunan diciptakan.

// Menambahkan konstruktor pada kelas Bangunan
using System;

class Bangunan
{
    public int Lantai; // jumlah lantai
    public int Luas; // luas bangunan
    public int Penghuni; // jumlah penghuni

    // Konstruktor terparameterisasi untuk Bangunan.
    public Bangunan(int f, int a, int o) {
      Lantai = f;
      Luas = a;
      Penghuni = o;
    }

    // Menampilkan luas per orang.
    public int LuasPerOrang() {
        return Luas / Penghuni;
    }

    // Memberikan nilai balik berupa jumlah maksimum penghuni
    // jika setiap penghuni sedikitnya memerlukan luas minimum
    // yang dispesifikasi.
    public int MaksPenghuni(int minLuas) {
        return Luas / minLuas;
    }
}

// menggunakan konstruktor Bangunan terparameterisasi.
class DemoBangunan
{
    static void Main()
    {
        Bangunan rumah = new Bangunan(2, 2500, 4);
        Bangunan kantor = new Bangunan(3, 4200, 25);

        Console.WriteLine("Penghuni maksimum rumah jika setiap penghuni mempunyai " +
                          30 + " meter persegi: " +
                          rumah.MaksPenghuni(30));

        Console.WriteLine("Penghuni maksimum kantor jika setiap penghuni mempunyai " +
                          30 + " meter persegi: " +
                          kantor.MaksPenghuni(30));
    }
}

Keluaran program ini sama dengan versi sebelumnya.

Kedua rumah dan kantor diinisialisasi dengan konstruktor Bangunan() ketika diciptakan. Setiap objek diinisialisasi seperti yang dispesifikasi di dalam parameter konstruktor. Sebagai contoh, pada baris berikut

Bangunan rumah = new Bangunan(2, 2500, 4);

nilai 2, 2500, dan 4 dilewatkan kepada konstruktor Bangunan() ketika new menciptakan objek. Jadi, salinan dari Lantai, Luas, dan Penghuni pada objek rumah akan memuat nilai 2, 2500, dan 4, berturut-turut.


Operator new
Setelah Anda mengetahui lebih banyak tentang kelas dan konstruktor, sekarang saatnya untuk melihat lebih dekat tentang operator new. Operator new mempunyai bentuk umum:

new nama-kelas(daftar-arg)

Di sini, nama-kelas adalah nama kelas yang sedang diinstansiasi. Nama kelas yang diikuti oleh sepasang kurung menspesifikasi konstruktor untuk kelas tersebut. Jika sebuah kelas tidak mendefinisikan konstruktornya sendiri, maka operator new akan menggunakan konstruktor default yang disediakan C#. Jadi, new dapat dipakai untuk menciptakan sebuah objek bertipe sembarang.

Bila memori terbatas, adalah hal mungkin bahwa new tidak bisa mengalokasikan memori untuk sebuah objek karena memori yang ada tidak cukup. Jika hal ini terjadi, eksepsi runtime akan terjadi. (Anda akan belajar tentang eksepsi pada Bab 12). Untuk semua program pada buku ini, Anda tidak perlu khawatir tentang kehabisan memori, tetapi Anda bisa saja mengalaminya ketika menulis program untuk menyelesaikan permasalahan di dunia aplikasi.



Menggunakan new Dengan Tipe Nilai
Pada titik ini, Anda mungkin bertanya mengapa Anda tidak perlu menggunakan new untuk variabel bertipe nilai, seperti int atau float? Dalam C#, variabel bertipe nilai memuat nilainya sendiri. Memori untuk menampung nilai ini secara otomatis disediakan ketika program dijalankan. Jadi, tidak ada kebutuhan untuk secara eksplisit mengalokasikan memori ini menggunakan new. Kebalikannya, variabel referensi menyimpan referensi yang menunjuk ke suatu objek. Memori untuk menampung objek ini harus dialokasikan secara dinamis selama eksekusi program berlangsung.


Pengumpulan Sampah dan Destruktor
Seperti yang Anda lihat, objek secara dinamis dialokasikan menggunakan operator new. Tentu saja, memori terbatas dan bisa habis. Oleh karena itu, adalah hal yang memungkinkan bila new gagal mengalokasikan memori karena memori tidak cukup untuk menciptakan objek yang diinginkan. Karena alasan ini, salah satu komponen kunci dari skema alokasi dinamis adalah pembebasan memori dari objek-objek yang tidak lagi digunakan. Pada banyak bahasa pemrograman, pembebasan memori dilakukan secara manual. Sebagai contoh, dalam C++, operator delete dipakai untuk membebaskan memori. Namun, C# menggunakan pendekatan lain: pengumpulan sampah!.

Sistem pengumpulan sampah memori dalam C# untuk membebaskan memori dilakukan secara otomatis, tanpa sepengetahuan programer. Mekanisme tersebut bekerja seperti ini: Ketika tidak ada referensi yang menunjuk ke sebuah objek, objek tersebut diasumsikan tidak lagi diperlukan, dan memori yang ditempati objek tersebut akan dibebaskan dan dikumpulkan.


Destruktor
Adalah hal yang memungkinkan bagi Anda untuk mendefinisikan sebuah metode yang dipanggil untuk menghancurkan suatu objek. Metode ini dikenal dengan destruktor dan bisa dipakai dalam situasi khusus untuk memastikan bahwa sebuah objek dihancurkan secara sempurna. Sebagai contoh, Anda bisa memakai destruktor untuk memastikan bahwa sumberdaya sistem yang dimiliki sebuah objek telah dibebaskan. Anda harus mengingat bahwa destruktor merupakan fitur tingkat tinggi yang hanya bisa diterapkan pada kasus-kasus tertentu dan jarang.

Destruktor mempunyai bentuk umum:

~nama-kelas( ) {
  // kode destruktor
}

Di sini, nama-kelas adalah nama kelas. Oleh karena itu, destruktor dideklarasikan seperti konstruktor kecuali bahwa ia diawali dengan suatu tilde (~). Perhatikan bahwa tidak ada tipe nilai balik dan tidak ada argumen.

Untuk menambahkan destruktor ke dalam sebuah kelas, Anda hanya perlu mencantumkannya sebagai anggota. Destruktor dipanggil kapanpun objek dari kelas tersebut dihancurkan. Di dalam destruktor, Anda bisa menspesifikasi aksi yang perlu dilakukan sebelum sebuah objek dihancurkan.
Program berikut mendemonstrasikan sebuah destruktor. Program bekerja dengan menciptakan dan menghancurkan banyak objek. Selama proses ini, pada titik tertentu kolektor sampah akan diaktivasi, dan destruktor untuk objek akan dipanggil.

// Demonstrasi destruktor.
using System;

class Hancur {
  public int x;
 
  public Hancur(int i) {
    x = i;
  }

  // dipanggil ketika objek dihancurkan.
  ~Hancur() {
    Console.WriteLine("Menghancurkan " + x);
  }

  // Membangkitkan sebuah objek yang dengan segera dihancurkan.
  public void Generator(int i) {
    Hancur o = new Hancur(i);
  }
}

class DemoDestruktor {
  static void Main() {
    int hitung;

    Hancur ob = new Hancur(0);

    /* Sekarang, sejumlah banyak objek dibangkitkan. Pada
       titik tertentu, kolektor sampah akan diaktivasi.
       Penting: Anda mungkin perlu menambah jumlah objek
       yang akan dibangkitkan untuk memaksa kolektor
       sampah diaktivasi */

    for(hitung=1; hitung < 100000; hitung++)
      ob.Generator(hitung);

    Console.WriteLine("Selasai");
  }
}

Berikut adalah bagaimana program bekerja. Konstruktor menetapkan variabel instans x dengan sebuah nilai. Pada contoh ini, x dipakai sebagai ID objek. Destruktor menampilkan nilai x ketika sebuah objek dihancurkan. Yang paling menarik di sini adalah Generator(). Metode ini menciptakan dan kemudian dengan segera menghapus objek Hancur. Kelas DemoDestruktor menciptakan objek Hancur yang dinamakan ob. Kemudian menggunakan ob, kelas ini menciptakan 100 ribu objek dengan memanggil metode Generator() pada ob. Hal ini menyebabkan penciptaan dan penghancuran 100 ribu objek. Pada titik tertentu di tengah proses ini, kolektor sampah akan diaktivasi, tergantung sistem operasi dan hal lainnya.


Katakunci this
Sebelum mengakhiri bab ini, penting untuk mengenalkan this.  Ketika sebuah metode dipanggil, ia secara otomatis melewatkan suatu referensi kepada objek pemanggil. Referensi ini dikenal dengan this. Untuk memahami ini, perhatikan program berikut yang menciptakan kelas bernama Persegi. Kelas ini mengenkapsulasi lebar dan tinggi suatu persegi panjang dan menyertakan sebuah metode yang bernama Luas() (yang menghasilkan nilai balik luas).

using System;

class Persegi {
  public int Lebar;
  public int Tinggi;
 
  public Persegi(int w, int h) {
    Lebar = w;
    Tinggi = h;
  }

  public int Luas() {
    return Lebar * Tinggi;
  }
}

class MenggunakanPersegi {
    static void Main() {
        Persegi r1 = new Persegi(4, 5);
        Persegi r2 = new Persegi(7, 9);
       
        Console.WriteLine("Luas dari r1: " + r1.Luas());
        Console.WriteLine("Luas dari r2: " + r2.Luas());
    }
}

Seperti Anda ketahui, di dalam sebuah metode, anggota lain dari sebuah kelas dapat diakses secara langsung, tanpa menggunakan objek atau kualifikasi kelas. Jadi, di dalam Luas(), statemen

return Lebar * Tinggi;

berarti bahwa salinan dari Lebar dan Tinggi yang berkaitan dengan objek pemanggil dapat dikalikan dan hasilnya dijadikan nilai balik. Namun, statemen yang sama dapat pula ditulis seperti ini:

return this.Lebar * this.Tinggi;

Di sini, this merujuk ke objek yang memanggil Luas(). Jadi, this.Lebar merujuk ke salinan dari Lebar pada objek pemanggil, dan this.Tinggi merujuk ke salinan dari Tinggi pada objek pemanggil. Sebagai contoh, jika Luas() dipanggil pada objek x, maka this pada statemen di atas akan menunjuk ke x. Penulisan statemen tanpa menggunakan this adalah cara singkat.

Hal yang memungkinkan juga untuk menggunakan this di dalam sebuah konstruktor. Pada kasus ini, this merujuk ke objek yang sedang diciptakan. Sebagai contoh, di dalam Persegi(), statemen

Lebar = w;
Tinggi = h;

dapat ditulis seperti ini:
this.Lebar = w;
this.Tinggi = h;

Tentu saja, tidak ada keuntungan dalam melakukan hal itu pada kasus ini. Agar dapat lebih dipahami, di sini kelas Persegi ditulis menggunakan referensi this:

using System;

class Persegi {
  public int Lebar;
  public int Tinggi;
 
  public Persegi(int w, int h) {
    this.Lebar = w;
    this.Tinggi = h;
  }

  public int Luas() {
    return Lebar * Tinggi;
  }
}

class MenggunakanPersegi {
    static void Main() {
        Persegi r1 = new Persegi(4, 5);
        Persegi r2 = new Persegi(7, 9);
       
        Console.WriteLine("Luas dari r1: " + r1.Luas());
        Console.WriteLine("Luas dari r2: " + r2.Luas());
    }
}





No comments:

Post a Comment