Menu
CoddyTech

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.

challenge icon

Tantangan

Mudah

Mari 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 struct Product dengan field Name yang diekspor dan field quantity yang tidak diekspor (int). Tambahkan method yang diekspor, Info() string, yang mengembalikan format: [Name]: [quantity] in stock
  • inventory.go: Buat fungsi pembantu yang bekerja dengan produk dengan mengakses field quantity yang 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 produk
    • Sell(p *Product, amount int) bool - mengurangi quantity jika stok mencukupi, mengembalikan true jika berhasil atau false jika stok tidak cukup
    • NewProduct(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 stock

Jika inputnya adalah Phone, 3, 2, dan 10, outputmu seharusnya:

Phone: 3 in stock
Phone: 5 in stock
Sale failed: insufficient stock

Inti 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
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Go online