November 15, 2025 (5mo ago) — last updated December 7, 2025 (4mo ago)

Kelas vs Structs: Kapan Menggunakan Masing-masing

Bandingkan kelas vs structs: pelajari kapan menggunakan tipe nilai atau referensi, bagaimana memori dan kinerja berbeda, serta aturan praktis untuk desain yang lebih baik.

← Back to blog
Cover Image for Kelas vs Structs: Kapan Menggunakan Masing-masing

Bandingkan kelas vs structs: pelajari kapan menggunakan tipe nilai atau referensi, bagaimana memori dan kinerja berbeda, serta aturan praktis untuk desain yang lebih baik.

Kelas vs Structs: Kapan Menggunakan Masing-masing

Ringkasan: Bandingkan kelas vs structs—nilai vs referensi, memori, kinerja, dan panduan desain untuk memilih jenis yang tepat demi kode yang efisien.

Pendahuluan

Memutuskan antara kelas dan struct lebih bersifat semantik daripada sintaksis. Pertanyaan kuncinya adalah apakah Anda memerlukan semantik nilai (menyalin data) atau semantik referensi (identitas bersama). Perbedaan itu memengaruhi penggunaan memori, kinerja, mutabilitas, dan arsitektur. Panduan ini menjelaskan trade-off tersebut dan memberi aturan praktis untuk memilih jenis yang tepat.

Perbedaan inti: semantik nilai vs referensi

Seorang programmer membandingkan blok kode untuk kelas dan struktur di layar besar.

Jika Anda menghapus sintaks bahasa, perdebatan kelas versus struct adalah percakapan tentang tipe nilai versus tipe referensi. Pikirkan struct seperti buku catatan yang difotokopi: Anda memberikan catatan Anda kepada seseorang dan mereka mendapatkan salinan mereka sendiri. Mereka bisa coret-coret tanpa mengubah aslinya. Itu adalah semantik nilai—salinan yang aman dan terisolasi. Kelas seperti dokumen bersama: Anda mengirimkan tautan dan semua orang mengedit objek yang sama secara langsung. Itu adalah semantik referensi—identitas bersama dan status bersama.

Perbedaan utama sekilas

CharacteristicStructs (Value Types)Classes (Reference Types)
Data handlingData is copied when passedA reference (pointer) is passed
Memory allocationOften stored inline or on the stackAllocated on the heap
LifecycleShort-lived, ephemeral copiesLong-lived, shared instances
IdentityDefined by data equalityDistinct identity independent of data
InheritanceUsually no inheritanceSupports inheritance and polymorphism
Primary use caseSmall, self-contained valuesComplex entities with behaviour

Prinsip-prinsip ini memiliki konsekuensi praktis terhadap latensi, penggunaan memori, dan ketepatan. Memilih dengan sengaja akan membuat kode Anda lebih dapat diprediksi dan lebih mudah dipelihara.

Bagaimana alokasi memori memengaruhi kinerja

Diagram yang menunjukkan perbedaan antara alokasi memori stack dan heap.

Stack dan heap adalah sumber utama efek kinerja dari keputusan ini.

Stack: cepat dan dapat diprediksi

Stack adalah wilayah memori LIFO di mana data lokal fungsi didorong dan dipop. Alokasi di stack sangat murah karena hanya aritmatika pointer. Untuk tipe nilai kecil, alokasi dan dealokasi hampir gratis.

Heap: fleksibel tetapi lebih mahal

Heap memungkinkan objek hidup melebihi satu panggilan fungsi, tetapi alokasi heap lebih lambat dan dapat memicu garbage collection atau dealokasi manual. Tipe referensi memperkenalkan indirection ekstra: stack menyimpan pointer ke data di heap. Alokasi heap berulang meningkatkan tekanan GC dan dapat menyebabkan jeda pada runtime yang dikelola1.

Contoh C#

// Value Type - lives inline (often on the stack)
public struct PointStruct {
    public int X;
    public int Y;
}

// Reference Type - object lives on the heap
public class PointClass {
    public int X;
    public int Y;
}

public void ProcessPoints() {
    PointStruct p1 = new PointStruct { X = 10, Y = 20 };
    PointClass p2 = new PointClass { X = 10, Y = 20 };
}

Dalam loop yang ketat, ribuan alokasi heap untuk objek kecil dapat secara signifikan meningkatkan aktivitas GC; structs dalam array sering kali mencapai lokalitas cache yang jauh lebih baik dan tekanan GC yang lebih rendah2.

Bagaimana bahasa memperlakukan kelas dan structs

Layar terbagi yang menunjukkan potongan kode dari berbagai bahasa pemrograman, menggambarkan kelas dan struktur.

Berbagai bahasa menekankan default yang berbeda. Pilihan terbaik bergantung pada idiom bahasa sama halnya dengan kinerja mentah.

C++: kata kunci hampir identik

Di C++, struct dan class hampir sama; perbedaan teknisnya hanya akses default (public untuk struct, private untuk class). Gunakan struct untuk agregat data polos dan class untuk tipe yang dikapsulkan dan perilaku kompleks3.

C#: pemisahan nilai/referensi yang jelas

C# membuat perbedaan itu eksplisit: struct adalah tipe nilai sejati, dan class adalah tipe referensi. Gunakan struct untuk nilai kecil yang tidak dapat diubah (koordinat, warna) dan kelas untuk entitas dengan identitas dan status bersama yang dapat diubah.

Swift: utamakan tipe nilai

Swift mendorong pendekatan yang mengutamakan nilai. Panduan Apple dan komunitas Swift lebih memilih struct secara default dan menyimpan class untuk kasus yang memerlukan semantik referensi, seperti status bersama yang dapat diubah atau interaksi dengan API Objective-C4.

Rust: kepemilikan dan keselamatan

Rust menggunakan struct ditambah model kepemilikan dan peminjaman untuk menyediakan keselamatan memori tanpa garbage collector. Perilaku dilampirkan melalui blok impl, dan kompiler menegakkan aturan kepemilikan dan peminjaman pada waktu kompilasi, mencegah banyak bug shared-state sebelum runtime5.

struct Player {
    username: String,
    level: u32,
    is_active: bool,
}

impl Player {
    fn level_up(&mut self) {
        self.level += 1;
    }
}

Pendekatan Rust memberi Anda kinerja kontrol memori langsung dengan jaminan keselamatan pada waktu kompilasi.

Kapan memilih struct untuk kinerja yang lebih baik

Pilih struct ketika tipe tersebut kecil, mandiri, dan diperlakukan seperti nilai daripada identitas. Kandidat khas:

  • Titik geometri (Point2D)
  • Nilai warna (RGB/RGBA)
  • Muatan konfigurasi kecil
  • Input komputasi ringan

Keuntungannya termasuk lebih sedikit alokasi heap, lokalitas cache yang lebih baik, dan tekanan GC yang lebih rendah di runtime yang dikelola. Lokalitas cache yang meningkat dapat menghasilkan percepatan besar pada loop yang banyak memproses data karena pola akses memori menjadi lebih ramah CPU2.

Kapan memilih kelas untuk memodelkan perilaku kompleks

Pilih kelas ketika sebuah objek memiliki identitas yang stabil, status bersama yang dapat diubah, atau ketika Anda memerlukan pewarisan atau manajemen siklus hidup yang kompleks. Kandidat khas:

  • Profil pengguna atau entitas domain
  • Objek koneksi database atau jaringan
  • Layanan dan manajer yang mengoordinasikan status

Kelas adalah dasar banyak pola berorientasi objek. Pewarisan dan polimorfisme mempermudah memodelkan hubungan dan perilaku yang kompleks.

Daftar periksa keputusan: struct vs class

ConsiderationUse struct (value)Use class (reference)
IdentityData is identityObject has unique identity
MutabilityImmutable or small, isolated stateShared, mutable state
BehaviorSimple logic tied to dataComplex interactions and behaviour
LifecycleShort-lived, local scopeLong-lived, application-wide
SharingSafe to copyMust be shared by reference

Pertanyaan umum

Apakah sebuah struct bisa memiliki metode?

Bisa. Bahasa modern seperti C#, Swift, dan Rust memungkinkan struct memiliki metode, initializer, dan kepatuhan terhadap protokol atau interface. Perbedaan utama tetap bagaimana mereka disalin dan dipass.

Apakah structs selalu lebih cepat?

Tidak. Struct kecil seringkali lebih cepat daripada objek yang dialokasikan di heap, tetapi struct besar bisa menjadi mahal untuk disalin. Selalu ukur: profilkan beban kerja nyata sebelum membuat perubahan besar.

Apakah structs mendukung pewarisan?

Biasanya tidak. Struct jarang mendukung pewarisan, tetapi banyak bahasa memungkinkan struct mengimplementasikan interface atau protokol, memungkinkan komposisi yang fleksibel tanpa rantai pewarisan yang dalam.

Tanya jawab praktis

T: Kapan saya harus merombak (refactor) sebuah kelas menjadi struct?

A: Refaktor ketika tipe tersebut adalah nilai kecil yang immutable tanpa identitas unik, dan Anda menginginkan lebih sedikit alokasi heap serta semantik nilai yang lebih jelas.

T: Bagaimana saya menghindari jeda GC di bahasa yang dikelola?

A: Kurangi alokasi heap jangka pendek dengan lebih memilih struct untuk nilai kecil, menggunakan kembali objek, dan memakai object pool; ukur perilaku GC di bawah beban1.

T: Apa aturan mudah yang paling sederhana?

A: Jika objek merepresentasikan “sebuah nilai” gunakan struct; jika merepresentasikan “sesuatu dengan identitas” gunakan kelas.

Tiga bagian Q&A singkat

Q&A 1 — Trade-off kinerja

Q: Apakah beralih ke structs selalu meningkatkan kecepatan? A: Tidak. Gunakan struct untuk nilai kecil yang sering dibuat untuk mengurangi tekanan GC dan meningkatkan lokalitas cache; hindari struct besar yang mahal untuk disalin.

Q&A 2 — Keamanan dan ketepatan

Q: Apakah structs mengurangi bug akibat status bersama? A: Ya. Semantik nilai mencegah mutasi bersama secara tidak sengaja, yang mengurangi bug terkait konkurensi dan status ketika nilai disalin alih-alih dibagikan.

Q&A 3 — Desain dan arsitektur

Q: Kapan kelas lebih baik daripada struct sebagai model? A: Gunakan kelas ketika identitas, siklus hidup jangka panjang, atau pewarisan dan polimorfisme diperlukan.


Di Clean Code Guy, kami membantu tim merombak untuk skalabilitas dan keterpeliharaan. Pelajari lebih lanjut di https://cleancodeguy.com.

1.
Microsoft Docs. “Garbage collection performance and tuning.” https://learn.microsoft.com/dotnet/standard/garbage-collection/
2.
Ulrich Drepper. “What Every Programmer Should Know About Memory.” https://people.freebsd.org/~lstewart/articles/cpumemory.pdf
3.
cppreference.com. “class vs struct.” https://en.cppreference.com/w/cpp/language/class
4.
Apple. “Structures and Classes” (Swift Programming Language). https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
5.
The Rust Programming Language. “Ownership.” https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html
← Back to blog
🙋🏻‍♂️

AI menulis kode.
Anda membuatnya bertahan.

Di era akselerasi AI, kode bersih bukan hanya praktik yang baik — ini adalah perbedaan antara sistem yang berkembang dan codebase yang runtuh di bawah beratnya sendiri.