Aplikasi perbankan menyimpan saldo di dalam sebuah class. Bila field saldo bersifat publik, kode mana pun dapat mengubahnya langsung, misalnya menuliskan nilai minus tanpa pemeriksaan apa pun. Encapsulation menyelesaikan masalah tersebut dengan menyembunyikan data di dalam class dan menyediakan jalur akses yang terkontrol. Prinsip ini menjadi fondasi desain class yang sehat sebelum kita masuk ke inheritance dan polymorphism.

Masalah Field Publik #

Bayangkan class RekeningBank dengan field public int saldo. Kode pemanggil bebas menuliskan rekening.saldo = -50000;, dan nilai yang tidak masuk akal itu langsung tersimpan. Tidak ada satu pun tempat untuk memasang aturan, karena setiap penulisan terjadi langsung pada field. Begitu aturan bisnis berubah, kita harus mencari semua baris yang menyentuh field tersebut di seluruh program.

Mekanisme: private, Property, dan Method #

C# menyediakan tiga alat utama untuk encapsulation:

  • private menyembunyikan field dari luar class; hanya kode di dalam class yang boleh membaca dan menulisnya.
  • Property dengan aksesor get membuka akses baca tanpa membuka akses tulis.
  • Method publik seperti Setor() dan Tarik() menjadi satu-satunya jalur perubahan data, sehingga validasi cukup dipasang di satu tempat.

Contoh: Class RekeningBank #

csharp
public class RekeningBank
{
    private int saldo;

    public RekeningBank(int saldoAwal)
    {
        saldo = saldoAwal;
    }

    public int Saldo
    {
        get { return saldo; }
    }

    public void Setor(int jumlah)
    {
        if (jumlah > 0)
        {
            saldo = saldo + jumlah;
        }
    }

    public void Tarik(int jumlah)
    {
        if (jumlah > 0 && jumlah <= saldo)
        {
            saldo = saldo - jumlah;
        }
        else
        {
            Console.WriteLine("Penarikan ditolak: jumlah tidak valid atau melebihi saldo.");
        }
    }
}

RekeningBank rekening = new RekeningBank(200000);
Console.WriteLine($"Saldo awal: Rp{rekening.Saldo}");
rekening.Setor(150000);
rekening.Tarik(500000);
rekening.Tarik(100000);
Console.WriteLine($"Saldo akhir: Rp{rekening.Saldo}");

Output yang Dihasilkan:

text
Saldo awal: Rp200000
Penarikan ditolak: jumlah tidak valid atau melebihi saldo.
Saldo akhir: Rp250000

Mari kita bedah baris demi baris:

  1. private int saldo;: Field saldo hanya dapat diakses dari dalam RekeningBank; kode luar tidak melihatnya sama sekali.
  2. Constructor RekeningBank(int saldoAwal): Nilai awal saldo hanya dapat ditentukan saat object dibuat.
  3. public int Saldo { get { return saldo; } }: Property ini hanya punya aksesor get, sehingga kode luar bisa membaca saldo tetapi tidak bisa menimpanya.
  4. Setor(int jumlah): Saldo bertambah hanya bila jumlah bernilai positif; permintaan lain diabaikan.
  5. Tarik(int jumlah): Penarikan diterima hanya bila jumlahnya positif dan tidak melebihi saldo; percobaan menarik 500000 pada saldo 350000 menghasilkan pesan penolakan, dan saldo tetap 350000.
text
error CS0122: 'RekeningBank.saldo' is inaccessible due to its protection level

Dengan encapsulation, aturan saldo hidup di satu tempat, dan semua kode pemanggil otomatis mengikuti aturan tersebut. Pola field privat plus property dan method terkontrol ini akan kita pakai berulang kali pada bab-bab berikutnya.