Paket Seviyesinde Kapsülleme
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 48 / 107.
Önceki derste alan düzeyindeki görünürlük ele alınmış olsa da Go'nun kapsülleme mekanizması aslında paket düzeyinde çalışır. Dosyanın hangisinde bulunduğuna bakılmaksızın aynı paket içindeki her şey, dışa aktarılmamış alanlara ve işlevlere erişebilir.
Birden fazla dosya içeren bir paketi göz önünde bulundurun:
// account/account.go
package account
type Account struct {
balance int // dışa aktarılmamış
}
func (a *Account) Deposit(amount int) {
a.balance += amount
}
// account/helper.go
package account
func ResetAccount(a *Account) {
a.balance = 0 // çalışır - aynı paket
}
Her iki dosya da account paketine aittir; bu nedenle helper.go, dışa aktarılmamış balance alanına directly erişebilir. Bu kasıtlıdır. Paket içi erişimi korurken paket mantığını dosyalar arasında bölmenize olanak tanır.
Ancak paketin dışındaki kod, dışa aktarılmamış üyelere erişemez:
// main.go
package main
import "account"
func main() {
acc := &account.Account{}
acc.Deposit(100) // çalışır - dışa aktarılmış metot
// acc.balance = 50 // hata - dışa aktarılmamış alan
// account.ResetAccount // ResetAccount dışa aktarılmış olsaydı çalışır
}
Bu paket düzeyi sınırı, Go’nun temel kapsülleme mekanizmasıdır. Paketleri, iç kodun özgürce iş birliği yaptığı, dış kodun ise yalnızca dışa aktarılan API aracılığıyla etkileşim kurduğu uyumlu birimler olarak tasarlarsınız. Her paketi, net bir genel arayüze sahip, kendi kendine yeten bir modül olarak düşünün.
Görev
KolayAynı paket içindeki birden fazla dosyanın, dış koddaki verileri gizli tutarken dışa aktarılmamış alanlara doğrudan erişerek nasıl birlikte çalışabileceğini gösteren bir envanter yönetim sistemi oluşturalım.
main paketinde birlikte çalışan üç dosya oluşturacaksın:
product.go: Dışa aktarılmış birProductalanına ve dışa aktarılmamış birNamealanına (int) sahip birquantityyapısı tanımla.Info() stringbiçimini döndüren dışa aktarılmış bir[Name]: [quantity] in stockmetodu ekle.inventory.go: Dışa aktarılmamışquantityalanına doğrudan erişerek ürünlerle çalışan yardımcı fonksiyonlar oluştur (aynı pakette oldukları için bu mümkündür). Şunları uygula:Restock(p *Product, amount int)- miktarı ürünün quantity değerine eklerSell(p *Product, amount int) bool- yeterli stok varsa miktarı quantity değerinden çıkarır; işlem başarılıysatrue, yeterli stok yoksafalsedöndürürNewProduct(name string, initialQty int) *Product- verilen ad ve başlangıç miktarıyla bir ürün oluşturan kurucu
main.go: Ürün bilgilerini girdiden oku, kurucuyu kullanarak bir ürün oluştur, envanter işlemlerini gerçekleştir ve sonuçları görüntüle. Güncellenmiş durumu göstermek için her işlemden sonra ürün bilgilerini yazdır.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Ürün adı
- 2. satır: Başlangıç miktarı (tam sayı)
- 3. satır: Stok yenileme miktarı (tam sayı)
- 4. satır: Satış miktarı (tam sayı)
Ürünü oluşturduktan sonra başlangıç bilgilerini yazdır. Ardından stok yenileme işlemini gerçekleştir ve bilgileri tekrar yazdır. Son olarak satışı gerçekleştirmeyi dene ve başarılıysa güncellenmiş bilgileri, miktar yeterli değilse Sale failed: insufficient stock ifadesini yazdır.
Örneğin, Laptop, 10, 5 ve 8 verildiğinde çıktın şu şekilde olmalıdır:
Laptop: 10 in stock
Laptop: 15 in stock
Laptop: 7 in stockVe Phone, 3, 2 ve 10 verildiğinde çıktın şu şekilde olmalıdır:
Phone: 3 in stock
Phone: 5 in stock
Sale failed: insufficient stockBuradaki temel çıkarım, inventory.go dosyasının dışa aktarılmamış quantity alanını doğrudan okuyup değiştirebilmesidir; çünkü product.go ile aynı pakettedir. Bu, paket düzeyinde kapsüllemenin işleyiş hâlidir: dahili iş birliği serbestçe gerçekleşirken veriler dış paketlerden korunmaya devam eder.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Ürün adını oku
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
// Başlangıç miktarını oku
initialQtyStr, _ := reader.ReadString('\n')
initialQty, _ := strconv.Atoi(strings.TrimSpace(initialQtyStr))
// Yeniden stok miktarını oku
restockStr, _ := reader.ReadString('\n')
restockAmount, _ := strconv.Atoi(strings.TrimSpace(restockStr))
// Satış miktarını oku
sellStr, _ := reader.ReadString('\n')
sellAmount, _ := strconv.Atoi(strings.TrimSpace(sellStr))
// TODO: NewProduct yapıcısını kullanarak yeni bir ürün oluştur
// TODO: Başlangıç ürün bilgisini yazdır
// TODO: Ürünü yeniden stokla ve bilgiyi yazdır
// TODO: Satış yapmayı dene ve sonucu yazdır
// Satış başarılı olursa, güncellenmiş bilgiyi yazdır
// If sale fails, print "Sale failed: insufficient stock"
fmt.Println() // Gerçek çıktı ile değiştir
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1Go OOP Temelleri
Harici DosyalarGo Çalışma Alanı ve ModüllerPaketler ve İçe AktarmalarDışa Aktarılan ve Aktarılmayan İsimlerGo'da OOP'ye GirişSınıf Olarak Struct'larStruct'larda Metot TanımlamaPointer ve Değer AlıcılarStruct BaşlatmaYapıcı FonksiyonlarÖzet - Basit Hesap Makinesi4Arayüzler
Arayüzlere GirişÖrtük UygulamaSözleşme Olarak ArayüzBoş Arayüz (any)Tür OnaylamaTür SeçimiArayüz BileşimiStringer ve Error ArayüzleriÖzet - Şekil Hesaplayıcı7Kapsülleme
Dışa Aktarılan ve Aktarılmayan AlanlarPaket Seviyesinde KapsüllemeGetter ve Setter MetotlarıGo'da Bilgi GizlemeÖzet - Öğrenci Kayıtları10Generics (Go 1.18+)
Generics'e GirişTür ParametreleriTür KısıtlamalarıGeneric Struct'larGeneric Metotlar İçin Geçici ÇözümÖzet - Generic Koleksiyon13Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıAbstract Factory KalıbıObserver KalıbıStrategy Kalıbı2Türler ve Struct'lar: Derinlemesine İnceleme
Temel ve Bileşik TürlerÖzel Tür TanımlamalarıStruct EtiketleriAnonim Struct'larİç İçe Geçmiş Struct'larSıfır Değerler ve VarsayılanlarÖzet - Rehber5Kalıtım Yerine Kompozisyon
Go'da Neden Kalıtım YokStruct Gömme TemelleriMetot YükseltmeBirden Fazla Struct GömmeGömme vs AgregasyonGömülü Metotları GölgelemeÖzet - Çalışan Hiyerarşisi8Hata Yönetimi ve OOP
error ArayüzüÖzel Hata TürleriHata Sarmalama (fmt.Errorf)Sentinel Hatalarerrors.Is() ve errors.As()Panic, Defer ve RecoverÖzet - Dosya Ayrıştırıcı3İşaretçiler ve Bellek
Go'da İşaretçi TemelleriStruct İşaretçileriDeğer ile Geçme ve Referans ile Geçmenew() FonksiyonuGo'da Garbage CollectionÖzet - Linked List Oluşturucu6Go'da Polimorfizm
Interface'ler ile PolimorfizmGo'da Duck TypingInterface Karşılama KurallarıPolimorfik KoleksiyonlarDependency InjectionÖzet - Payment Processor9Eşzamanlılık ve OOP
Goroutine TemelleriKanallar ve İletişimTamponlu ve Tamponsuz KanallarSelect İfadesisync.Mutex ve sync.RWMutexsync.WaitGroupThread-Safe Struct TasarımıÖzet - Worker PoolKendi başına pratik yap: Online Go derleyicisi