Topik ini membahas access modifier, yaitu kata kunci yang mengatur bagian mana program yang boleh mengakses sebuah anggota kelas. Materinya mencakup public, private, protected, dan internal, kemudian menerapkannya pada enkapsulasi (encapsulation, praktik menyembunyikan data internal dan membukanya lewat antarmuka yang terkendali). Setelah topik ini diselesaikan, batas akses setiap anggota dapat ditetapkan secara sadar, bukan sekadar mengikuti kebiasaan.
Peran access modifier dalam enkapsulasi#
Enkapsulasi menyimpan data sensitif kelas di tempat yang tidak dapat disentuh dari luar, lalu membukanya melalui metode atau property yang mengawasi setiap perubahan. Tanpa batas akses, bagian program mana pun bebas menulis data kelas apa adanya, dan aturan keabsahan data tidak lagi berada di satu tempat. Access modifier mengubah batas akses menjadi larangan yang ditegakkan kompilator, bukan sekadar kesepakatan penulisan.
Anggota kelas yang tidak diberi access modifier mana pun dianggap private, sehingga kunci paling aman untuk data internal adalah justru tidak menulis apa pun. Kelas tingkat atas yang tidak diberi modifier dianggap internal, sehingga kelas tersebut hanya terlihat di dalam assembly-nya. Kedua nilai default ini berarti kode biasanya sudah lebih tertutup daripada yang diperkirakan.
Tingkat akses dan cakupannya#
| Modifier | Cakupan akses |
|---|---|
public | Dapat diakses dari bagian program mana pun, termasuk assembly lain. |
private | Hanya dapat diakses dari dalam kelas yang mendeklarasikannya. |
protected | Dapat diakses dari kelas itu sendiri dan dari kelas turunannya. |
internal | Dapat diakses dari mana saja di dalam assembly yang sama, yaitu paket hasil kompilasi seperti satu berkas .dll atau .exe. |
Dua kombinasi tambahan, yaitu protected internal dan private protected, menggabungkan cakupan modifier-nya dengan aturan yang lebih rinci. Cakupan protected internal adalah gabungan keduanya, sedangkan private protected mempersempit protected internal kepada kelas turunan yang berada di assembly yang sama. Keduanya jarang dibutuhkan pada tahap awal, sehingga penguasaan empat modifier dasar sudah mencukupi untuk sebagian besar kebutuhan. Pemilihan modifier mengikuti satu pertanyaan, yaitu siapa pihak yang benar-benar memerlukan anggota tersebut, dan jawabannya menentukan cakupan terkecil yang masih memadai.
Access modifier dapat diterapkan pada kelas maupun pada anggotanya, dan keduanya bekerja pada lapisan yang berbeda. Modifier pada kelas menentukan keterlihatan tipe dari luar, sedangkan modifier pada anggota menentukan siapa yang boleh menyentuhnya dari dalam tipe yang sudah terlihat. Kelas internal dengan anggota public, misalnya, tetap tidak terlihat dari assembly lain karena pintu pertamanya saja yang tertutup.
Menerapkan enkapsulasi#
Program berikut menyembunyikan saldo di balik field private dan membukanya hanya melalui metode yang memeriksa keabsahan setiap perubahan. Aturannya sederhana, yaitu saldo hanya boleh berubah melalui penyetoran dan penarikan yang sah. Pembacaan saldo tetap tersedia untuk semua pihak tanpa membuka jalur penulisannya.
// Program: enkapsulasi saldo pada kelas Rekening dengan field privat.
var rekening = new Rekening("Dewi", 500000);
rekening.Setor(150000);
rekening.Tarik(200000);
Console.WriteLine(rekening.Pemilik);
Console.WriteLine(rekening.Saldo);
class Rekening
{
private int saldo;
public string Pemilik { get; }
public Rekening(string pemilik, int saldoAwal)
{
Pemilik = pemilik;
saldo = saldoAwal;
}
public void Setor(int jumlah)
{
if (jumlah > 0)
{
saldo += jumlah;
}
}
public void Tarik(int jumlah)
{
if (jumlah > 0 && jumlah <= saldo)
{
saldo -= jumlah;
}
}
public int Saldo => saldo;
}Dewi
450000Field saldo bertanda private, sehingga satu-satunya jalur mengubahnya adalah Setor dan Tarik yang masing-masing memeriksa syaratnya terlebih dahulu. Penarikan melebihi saldo atau penyetoran nilai negatif diabaikan tanpa pernah merusak data, dan pembacaan Saldo tersedia sebagai property terhitung tanpa aksesor set. Property Pemilik menggunakan { get; } karena data pemilik ditetapkan sekali oleh konstruktor dan tidak boleh berubah.
Konstruktor menerima data awal dan langsung mengisinya, sehingga object Rekening tidak pernah berada dalam keadaan setengah terisi. Metode Setor dan Tarik mengembalikan void karena keberhasilan operasinya dapat dilihat dari saldo, dan pemeriksaan yang gagal cukup diabaikan. Pemeriksaan pada awal metode semacam ini menjadi pelindung pertama data yang tersembunyi, dan penjagaannya berlaku untuk seluruh pemanggil tanpa kecuali.
Percobaan lain yang menarik adalah menyentuh field saldo secara langsung dari kode pemanggil. Percobaan semacam ini ditolak saat kompilasi, sebagaimana diperlihatkan potongan berikut. Kesalahan seperti ini sering muncul ketika kode lama disunting sebelum enkapsulasi diterapkan.
// tidak-dijalankan
Console.WriteLine(rekening.saldo);Kompilator menolaknya dengan error CS0122: 'Rekening.saldo' is inaccessible due to its protection level. Pesan tersebut menunjuk persis anggota yang tidak boleh disentuh, sehingga penyebabnya langsung terbaca. Larangan ini berlaku untuk seluruh assembly, sehingga aturan keabsahan saldo tidak dapat dilanggar bahkan oleh kode yang ditulis jauh setelah kelasnya selesai.
protected dan internal#
Modifier protected meluaskan akses private kepada kelas turunan. Anggota yang bertanda protected tetap tersembunyi dari kelas lain, tetapi kelas turunan bebas memakainya, sehingga cocok untuk utilitas yang memang bagian dari kontrak pewarisan. Dengan cakupan ini, utilitas bersama cukup dideklarasikan sekali di kelas dasar tanpa menjadi bagian antarmuka publiknya.
var sensor = new SensorTegangan();
sensor.Ukur();
class Perangkat
{
protected void Log(string pesan)
{
Console.WriteLine($"[log] {pesan}");
}
}
class SensorTegangan : Perangkat
{
public void Ukur()
{
Log("pengukuran tegangan selesai");
}
}[log] pengukuran tegangan selesaiModifier internal mengatur batas sebaliknya, yaitu membuka akses di seluruh assembly tetapi menutupnya dari assembly lain. Pustaka (library) memakai internal untuk utilitas pendukung yang tidak termasuk antarmuka publiknya. Pemakaiannya bebas di dalam pustaka tersebut, sedangkan pemanggil dari proyek lain tidak pernah melihatnya.
var utilitas = new Utilitas();
utilitas.Catat("program dimulai");
class Utilitas
{
internal void Catat(string pesan)
{
Console.WriteLine($"[catat] {pesan}");
}
}[catat] program dimulaiKarena satu program C# dikompilasi menjadi satu assembly, pemanggilan di atas sah dilakukan. Program yang terdiri atas banyak berkas pun tetap satu assembly bila dikompilasi bersama, sehingga batas internal-nya tetap sama. Pembedanya dengan public baru terlihat ketika assembly dipakai proyek lain, karena anggota internal tidak muncul di antarmuka yang dapat dipanggil dari luar.
Kesalahan umum#
- Menandai semua anggota
public. Kebebasan akses menghapus titik kendali enkapsulasi, sehingga data dapat berubah dari bagian program mana pun tanpa pemeriksaan. Tetapkanprivatesebagai titik awal, lalu naikkan cakupannya hanya untuk anggota yang benar-benar diperlukan dari luar. - Membuka field menjadi
publicdemi mengatasierror CS0122. Pesan tersebut muncul karena aksesnya memang tidak diizinkan, sedangkan perbaikan yang tepat adalah menyediakan metode atau property dengan aturan yang jelas. Membuka field langsung memindahkan kendali data dari kelas ke pemanggilnya. - Mengira anggota tanpa modifier bersifat
public. Anggota kelas tanpa modifier dianggapprivate, sehingga akses dari kelas lain ditolak tanpa pesan yang menyebut modifier. Tulis modifier secara eksplisit pada anggota yang memang dimaksudkan terbuka.
Ringkasan#
- Access modifier menegakkan enkapsulasi pada tingkat kompilator, sehingga batas akses bukan lagi kesepakatan tetapi larangan.
publicterbuka untuk semua,privateterbatas pada kelasnya,protectedmeluas ke kelas turunan, daninternalterbatas pada satu assembly.- Data internal dinyatakan
privatedan dibuka melalui metode atau property yang memeriksa setiap perubahan. - Anggota kelas tanpa modifier dianggap
private, sedangkan kelas tingkat atas tanpa modifier dianggapinternal.
Referensi#
- Access Modifiers — Microsoft Learn — Mendaftar access modifier C# beserta cakupan akses masing-masing.
- Access Modifiers (C# Programming Guide) — Microsoft Learn — Menjelaskan penerapan tingkat akses pada kelas dan anggota kelas.