Langsung ke konten
KamusNgoding
Menengah Csharp 3 menit baca

Class dan Object di C#: Dasar OOP

#csharp #class #object #oop #constructor #properties #encapsulation #record

C# adalah bahasa yang dibangun di atas fondasi OOP — bahkan program paling sederhana pun melibatkan class (Console adalah class, String adalah class). Memahami cara membuat class sendiri adalah langkah besar menuju pemrograman C# yang sesungguhnya. Dibanding C++ yang kita bahas sebelumnya (Class dan Object di C++), C# memiliki fitur properties bawaan yang membuat enkapsulasi jauh lebih elegan.

Membuat Class Pertama

public class RekeningBank
{
    // Fields private — data yang disembunyikan dari luar
    private string pemilik;
    private decimal saldo;
    private List<string> riwayat = new();

    // Constructor
    public RekeningBank(string namaPemilik, decimal saldoAwal)
    {
        pemilik = namaPemilik;
        saldo = saldoAwal;
        riwayat.Add($"Buka rekening: +Rp {saldoAwal:N0}");
    }

    // Method public
    public void Setor(decimal jumlah)
    {
        if (jumlah <= 0) throw new ArgumentException("Jumlah harus positif");
        saldo += jumlah;
        riwayat.Add($"Setor: +Rp {jumlah:N0} (saldo: {saldo:N0})");
        Console.WriteLine($"Setor berhasil. Saldo baru: Rp {saldo:N0}");
    }

    public bool Tarik(decimal jumlah)
    {
        if (jumlah > saldo)
        {
            Console.WriteLine("Saldo tidak cukup!");
            return false;
        }
        saldo -= jumlah;
        riwayat.Add($"Tarik: -Rp {jumlah:N0} (saldo: {saldo:N0})");
        Console.WriteLine($"Berhasil tarik Rp {jumlah:N0}. Saldo baru: Rp {saldo:N0}");
        return true;
    }

    public void CetakRiwayat()
    {
        Console.WriteLine($"\n=== Riwayat {pemilik} ===");
        foreach (var transaksi in riwayat)
            Console.WriteLine($"  {transaksi}");
    }
}

// Penggunaan
var rekening = new RekeningBank("Budi Santoso", 1_000_000m);
rekening.Setor(500_000m);
rekening.Tarik(200_000m);
rekening.CetakRiwayat();
// Output:
// Setor berhasil. Saldo baru: Rp 1.500.000
// Berhasil tarik Rp 200.000. Saldo baru: Rp 1.300.000
// === Riwayat Budi Santoso ===
//   Buka rekening: +Rp 1.000.000
//   Setor: +Rp 500.000 (saldo: 1.500.000)
//   Tarik: -Rp 200.000 (saldo: 1.300.000)

Properties: Fitur Unggulan C#

Properties adalah fitur C# yang tidak ada di C++ atau Java — mereka menggabungkan field dan getter/setter menjadi sintaks yang bersih:

public class Produk
{
    private string _nama;
    private decimal _harga;

    // Property dengan validasi
    public string Nama
    {
        get { return _nama; }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("Nama tidak boleh kosong");
            _nama = value.Trim();
        }
    }

    public decimal Harga
    {
        get { return _harga; }
        set
        {
            if (value < 0) throw new ArgumentException("Harga tidak boleh negatif");
            _harga = value;
        }
    }

    // Auto-property — tanpa backing field manual
    public int Stok { get; set; } = 0;

    // Read-only property
    public bool TersediaStok => Stok > 0;

    // Expression-bodied property
    public string Info => $"{Nama} — Rp {Harga:N0} (stok: {Stok})";

    public Produk(string nama, decimal harga, int stok = 0)
    {
        Nama = nama;   // Memanggil setter (ada validasi)
        Harga = harga;
        Stok = stok;
    }
}

var laptop = new Produk("ThinkPad X1", 15_000_000m, 5);
Console.WriteLine(laptop.Info);
// Output: ThinkPad X1 — Rp 15.000.000 (stok: 5)
Console.WriteLine(laptop.TersediaStok); // Output: True

laptop.Stok = 0;
Console.WriteLine(laptop.TersediaStok); // Output: False

// laptop.Harga = -1000; // ❌ Exception: Harga tidak boleh negatif

Object Initializer Syntax

// Inisialisasi properti tanpa constructor khusus
var buku = new Produk("Clean Code", 350_000m)
{
    Stok = 20
};

Console.WriteLine(buku.Info);
// Output: Clean Code — Rp 350.000 (stok: 20)

Static Members

static members milik class, bukan instance:

public class Counter
{
    private static int _total = 0;  // Satu untuk semua instance
    private int _id;

    public Counter()
    {
        _total++;
        _id = _total;
    }

    public static int Total => _total;
    public int Id => _id;

    public static void Reset() => _total = 0;
}

var c1 = new Counter();
var c2 = new Counter();
var c3 = new Counter();

Console.WriteLine(Counter.Total); // Output: 3 (akses via nama class, bukan instance)
Console.WriteLine(c1.Id);         // Output: 1
Console.WriteLine(c3.Id);         // Output: 3

Record Type — Immutable Data Class (C# 9+)

record adalah cara modern membuat class data yang immutable dan dengan equality berbasis nilai:

// record: semua properties read-only by default, equality berdasarkan nilai
public record Koordinat(double Latitude, double Longitude);

var jakarta = new Koordinat(-6.2088, 106.8456);
var surabaya = new Koordinat(-7.2575, 112.7521);

Console.WriteLine(jakarta);
// Output: Koordinat { Latitude = -6.2088, Longitude = 106.8456 }

// Equality berbasis nilai (bukan referensi)
var jakarta2 = new Koordinat(-6.2088, 106.8456);
Console.WriteLine(jakarta == jakarta2); // Output: True

// Membuat salinan dengan nilai yang diubah
var jakarta_baru = jakarta with { Latitude = -6.2100 };
Console.WriteLine(jakarta_baru);
// Output: Koordinat { Latitude = -6.21, Longitude = 106.8456 }

Constructor Overloading dan this()

public class Jadwal
{
    public string MataKuliah { get; }
    public string Dosen { get; }
    public string Ruang { get; }
    public int JamMulai { get; }

    // Constructor utama
    public Jadwal(string mataKuliah, string dosen, string ruang, int jamMulai)
    {
        MataKuliah = mataKuliah;
        Dosen = dosen;
        Ruang = ruang;
        JamMulai = jamMulai;
    }

    // Constructor dengan default dosen — memanggil constructor utama
    public Jadwal(string mataKuliah, string ruang, int jamMulai)
        : this(mataKuliah, "TBD", ruang, jamMulai) { }

    public override string ToString()
        => $"{MataKuliah} | {Dosen} | {Ruang} | Jam {JamMulai}:00";
}

var mk1 = new Jadwal("Algoritma", "Prof. Ali", "Lab A", 8);
var mk2 = new Jadwal("Database", "Lab B", 10); // Dosen TBD

Console.WriteLine(mk1); // Output: Algoritma | Prof. Ali | Lab A | Jam 8:00
Console.WriteLine(mk2); // Output: Database | TBD | Lab B | Jam 10:00

Pertanyaan yang Sering Diajukan

Apa perbedaan class dan record di C#?

class adalah reference type yang mutable (nilainya bisa diubah) dan equality-nya berdasarkan referensi (dua variabel yang isinya sama dianggap tidak sama jika tidak menunjuk objek yang sama). record menghasilkan class yang immutable by default dengan equality berdasarkan nilai — cocok untuk DTO (Data Transfer Object), event, atau data domain yang tidak berubah.

Kapan menggunakan auto-property vs property dengan backing field?

Gunakan auto-property (public string Nama { get; set; }) untuk properti sederhana tanpa logika. Gunakan property dengan backing field saat kamu perlu validasi (cek nilai sebelum diterima), transformasi (trim string), atau logika lainnya di getter/setter.

Mengapa naming convention C# menggunakan PascalCase untuk method dan property?

Ini adalah konvensi Microsoft yang sudah menjadi standar C# sejak awal. Method dan properti publik menggunakan PascalCase (NamaMethod), variabel lokal dan parameter menggunakan camelCase (namaVariabel), field private sering menggunakan _namaField dengan underscore. Mengikuti konvensi ini membuat kode C# konsisten dan mudah dibaca oleh semua developer C#.

Apakah record menggantikan class untuk semua kasus?

Tidak. record paling cocok untuk data yang merepresentasikan nilai (value object) yang tidak berubah setelah dibuat — seperti koordinat, DTO dari API, atau domain event. class tetap lebih cocok untuk entitas dengan identitas dan state yang berubah (seperti RekeningBank di contoh di atas).

Kesimpulan

KonsepC++C#
Enkapsulasiprivate: sectionAccess modifiers per member
PropertiesManual getter/setterNative get/set properties
ConstructorInitializer list: this() chaining
Destructor~Class() deterministicFinalizer non-deterministic
Immutable dataBuat manualrecord type
Staticstatic keywordstatic keyword + static class

Artikel sebelumnya: Koleksi Data di C# — List, Dictionary, dan LINQ.

Langkah selanjutnya: Inheritance dan Polymorphism di C# — cara membuat hierarki class dan polymorphism di C#.

Artikel Terkait