Enkapsulasi Tingkat Package
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 48 dari 107.
Meskipun pelajaran sebelumnya membahas visibilitas pada tingkat field, enkapsulasi Go sebenarnya beroperasi pada tingkat package. Semua yang berada dalam package yang sama, terlepas dari file tempatnya berada, dapat mengakses field dan fungsi yang tidak diekspor.
Pertimbangkan sebuah paket dengan beberapa file:
// account/account.go
package account
type Account struct {
balance int // tidak diekspor
}
func (a *Account) Deposit(amount int) {
a.balance += amount
}
// account/helper.go
package account
func ResetAccount(a *Account) {
a.balance = 0 // berfungsi karena berada dalam package yang sama
}
Kedua file termasuk dalam package account, jadi helper.go dapat langsung mengakses field balance yang tidak diekspor. Ini memang disengaja. Dengan begitu, kamu dapat membagi logika package ke beberapa file sambil mempertahankan akses internal.
Namun, kode di luar package tidak dapat mengakses anggota yang tidak diekspor:
// main.go
package main
import "account"
func main() {
acc := &account.Account{}
acc.Deposit(100) // berfungsi, method yang diekspor
// acc.balance = 50 // error, field yang tidak diekspor
// account.ResetAccount // berfungsi jika ResetAccount diekspor
}
Batas tingkat package ini adalah mekanisme enkapsulasi utama Go. Kamu merancang package sebagai unit yang padu, tempat kode internal bekerja sama secara leluasa, sementara kode eksternal hanya berinteraksi dengan API yang diekspor. Anggap setiap package sebagai module mandiri dengan antarmuka publik yang jelas.
Tantangan
MudahMari kita buat sistem manajemen inventaris yang menunjukkan cara beberapa file dalam paket yang sama dapat bekerja sama dengan mengakses field yang tidak diekspor secara langsung, sekaligus menyembunyikan data tersebut dari kode eksternal.
Kamu akan membuat tiga file yang bekerja sama dalam paket main:
product.go: Definisikan structProductdengan fieldNameyang diekspor dan fieldquantityyang tidak diekspor (int). Tambahkan method yang diekspor,Info() string, yang mengembalikan format:[Name]: [quantity] in stockinventory.go: Buat fungsi pembantu yang bekerja dengan produk dengan mengakses fieldquantityyang tidak diekspor secara langsung (hal ini memungkinkan karena semuanya berada dalam paket yang sama). Implementasikan:Restock(p *Product, amount int)- menambahkan jumlah tersebut ke quantity produkSell(p *Product, amount int) bool- mengurangi quantity jika stok mencukupi, mengembalikantruejika berhasil ataufalsejika stok tidak cukupNewProduct(name string, initialQty int) *Product- konstruktor yang membuat produk dengan nama dan quantity awal yang diberikan
main.go: Baca detail produk dari input, buat produk menggunakan konstruktor, lakukan operasi inventaris, lalu tampilkan hasilnya. Setelah setiap operasi, cetak info produk untuk menunjukkan keadaan terbaru.
Input berikut akan diberikan:
- Baris 1: Nama produk
- Baris 2: Quantity awal (bilangan bulat)
- Baris 3: Jumlah yang ditambahkan ke stok (bilangan bulat)
- Baris 4: Jumlah yang dijual (bilangan bulat)
Setelah membuat produk, cetak info awalnya. Lalu tambahkan stok dan cetak infonya lagi. Terakhir, coba lakukan penjualan dan cetak info terbaru jika berhasil, atau Sale failed: insufficient stock jika quantity tidak cukup.
Misalnya, jika inputnya adalah Laptop, 10, 5, dan 8, outputmu seharusnya:
Laptop: 10 in stock
Laptop: 15 in stock
Laptop: 7 in stockJika inputnya adalah Phone, 3, 2, dan 10, outputmu seharusnya:
Phone: 3 in stock
Phone: 5 in stock
Sale failed: insufficient stockInti pentingnya adalah inventory.go dapat membaca dan mengubah field quantity yang tidak diekspor secara langsung karena file tersebut berada dalam paket yang sama dengan product.go. Inilah enkapsulasi tingkat paket: kolaborasi internal dapat berlangsung dengan leluasa, sementara data tetap terlindungi dari paket luar.
Coba sendiri
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Baca nama produk
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
// Baca jumlah awal
initialQtyStr, _ := reader.ReadString('\n')
initialQty, _ := strconv.Atoi(strings.TrimSpace(initialQtyStr))
// Baca jumlah penambahan stok
restockStr, _ := reader.ReadString('\n')
restockAmount, _ := strconv.Atoi(strings.TrimSpace(restockStr))
// Baca jumlah yang akan dijual
sellStr, _ := reader.ReadString('\n')
sellAmount, _ := strconv.Atoi(strings.TrimSpace(sellStr))
// TODO: Buat produk baru menggunakan konstruktor NewProduct
// TODO: Tampilkan informasi awal produk
// TODO: Tambah stok produk dan tampilkan informasinya
// TODO: Coba jual produk dan tampilkan hasilnya
// Jika penjualan berhasil, tampilkan informasi terbaru
// Jika penjualan gagal, tampilkan "Sale failed: insufficient stock"
fmt.Println() // Ganti dengan output yang sebenarnya
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online