Menu
Coddy logo textTech

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 ders alan düzeyinde görünürlüğü kapsamış olsa da, Go'nun kapsülleme mekanizması aslında paket düzeyinde çalışır. Aynı paket içindeki her şey —hangi dosyada olduğuna bakılmaksızın— dışa aktarılmamış (unexported) alanlara ve fonksiyonlara erişebilir.

Birden fazla dosyaya sahip bir paketi düşünün:

// 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 doğrudan erişebilir. Bu bilinçli bir tercihtir; dahili erişimi korurken paket mantığını dosyalar arasında bölmenize olanak tanır.

Ancak, paket dışındaki kodlar dışa aktarılmamış (unexported) ü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ışırdı
}

Bu paket düzeyindeki sınır, Go'nun birincil kapsülleme mekanizmasıdır. Paketleri, dahili kodun serbestçe iş birliği yaptığı, harici kodun ise yalnızca dışa aktarılan API aracılığıyla etkileşime girdiği uyumlu birimler olarak tasarlarsınız. Her paketi, net bir genel arayüze sahip, kendi kendine yeten bir modül olarak düşünün.

challenge icon

Görev

Kolay

Aynı paket içindeki birden fazla dosyanın, dış kodlardan verileri gizli tutarken, dışa aktarılmamış (unexported) alanlara doğrudan erişerek nasıl birlikte çalışabileceğini gösteren bir envanter yönetim sistemi kuralım.

main paketi içinde birlikte çalışan üç dosya oluşturacaksınız:

  • product.go: Dışa aktarılmış bir Name alanına ve dışa aktarılmamış bir quantity alanına (int) sahip bir Product yapısı (struct) tanımlayın. Şu formatı döndüren dışa aktarılmış bir Info() string metodu ekleyin: [Name]: [quantity] in stock
  • inventory.go: Dışa aktarılmamış quantity alanına doğrudan erişerek (aynı pakette oldukları için mümkündür) ürünlerle çalışan yardımcı fonksiyonlar oluşturun. Şunları uygulayın:
    • Restock(p *Product, amount int) - miktarı ürünün adedine ekler
    • Sell(p *Product, amount int) bool - yeterli stok varsa miktarı adetten çıkarır, başarılıysa true, yeterli stok yoksa false döndürür
    • NewProduct(name string, initialQty int) *Product - verilen isim ve başlangıç miktarıyla bir ürün oluşturan yapıcı (constructor) fonksiyon
  • main.go: Girdiden ürün detaylarını okuyun, yapıcıyı kullanarak bir ürün oluşturun, envanter işlemlerini gerçekleştirin ve sonuçları görüntüleyin. Her işlemden sonra, güncellenmiş durumu göstermek için ürün bilgisini yazdırın.

Aşağıdaki girdiler sağlanacaktır:

  • Satır 1: Ürün adı
  • Satır 2: Başlangıç miktarı (tam sayı)
  • Satır 3: Stok ekleme miktarı (tam sayı)
  • Satır 4: Satış miktarı (tam sayı)

Ürünü oluşturduktan sonra başlangıç bilgisini yazdırın. Ardından stok ekleyin ve bilgiyi tekrar yazdırın. Son olarak, satış yapmayı deneyin ve ya güncellenmiş bilgiyi (başarılıysa) ya da Sale failed: insufficient stock (yeterli miktar yoksa) yazdırın.

Örneğin, Laptop, 10, 5 ve 8 verildiğinde çıktınız şöyle olmalıdır:

Laptop: 10 in stock
Laptop: 15 in stock
Laptop: 7 in stock

Ve Phone, 3, 2 ve 10 verildiğinde çıktınız şöyle olmalıdır:

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

Buradaki temel nokta, inventory.go dosyasının product.go ile aynı pakette olduğu için dışa aktarılmamış quantity alanını doğrudan okuyabilmesi ve değiştirebilmesidir. Bu, paket düzeyinde kapsüllemenin (encapsulation) bir örneğidir; veriler dış paketlerden korunurken paket içi iş birliği serbestçe gerçekleşir.

Kopya kağıdı

Go'un kapsülleme (encapsulation) mekanizması dosya düzeyinde değil, paket düzeyinde çalışır. Aynı paket içindeki tüm dosyalar, hangi dosyada tanımlandıklarına bakılmaksızın dışa aktarılmamış (unexported) alanlara ve fonksiyonlara erişebilir.

Paket Düzeyinde Erişim

Dışa aktarılmamış üyeler, aynı paketteki tüm dosyalar arasında erişilebilirdir:

// 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
}

Harici Paket Kısıtlamaları

Paket dışındaki kodlar, 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
}

Bu tasarım, dahili erişimi korurken paket mantığını birden fazla dosyaya bölmenize olanak tanıyarak net genel (public) arayüzlere sahip uyumlu birimler oluşturmanızı sağlar.

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))

	// Stok yenileme 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ısını kullanarak yeni bir ürün oluşturun

	// TODO: Başlangıç ürün bilgilerini yazdırın

	// TODO: Ürün stoğunu yenileyin ve bilgileri yazdırın

	// TODO: Satış yapmayı deneyin ve sonucu yazdırın
	// Satış başarılı olursa, güncellenmiş bilgileri yazdırın
	// Satış başarısız olursa, "Sale failed: insufficient stock" yazdırın

	fmt.Println() // Gerçek çıktı ile değiştirin
}
quiz iconKendini test et

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