Menu
Coddy logo textTech

Polimorfik Koleksiyonlar

Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 44 / 107.

Arayüzlerin en güçlü uygulamalarından biri, farklı türleri aynı koleksiyonda saklamaktır. Bir arayüz türündeki slice, o arayüzü karşılayan herhangi bir değeri tutabilir ve bu da ilgili ancak farklı türleri bir arada gruplandırmanıza olanak tanır.

Çeşitli şekilleri yönetmeniz gereken bir senaryo düşünün. Her tür için ayrı dilimler (slice) kullanmak yerine, arayüz (interface) türünde tek bir dilim kullanabilirsiniz:

type Shape interface {
    Area() float64
}

type Circle struct{ Radius float64 }
func (c Circle) Area() float64 { return 3.14159 * c.Radius * c.Radius }

type Rectangle struct{ Width, Height float64 }
func (r Rectangle) Area() float64 { return r.Width * r.Height }

func main() {
    shapes := []Shape{
        Circle{Radius: 5},
        Rectangle{Width: 4, Height: 3},
        Circle{Radius: 2},
    }
    
    for _, s := range shapes {
        fmt.Printf("Area: %.2f\n", s.Area())
    }
}

shapes dilimi hem daireleri hem de dikdörtgenleri tutar. Yineleme sırasında, her öğe kendi gerçek türüne göre Area() metoduna yanıt verir. Bu, koleksiyonlara uygulanan polimorfizmdir; aynı döngü tüm şekil türlerini tek tip bir şekilde işler.

Çeşitli öğeleri işleyen sistemler oluştururken polimorfik koleksiyonlar temel öneme sahiptir: e-posta ve SMS mesajları gönderen bir bildirim sistemi, farklı düşman türlerini güncelleyen bir oyun veya birden fazla dosya formatını işleyen bir belge işlemcisi. Koleksiyon belirli türlerle ilgilenmez; yalnızca her öğenin gerekli davranışı sağlamasıyla ilgilenir.

challenge icon

Görev

Kolay

Farklı görev türlerini birleşik bir arayüz üzerinden yöneten bir görev yönetim sistemi oluşturalım. Çeşitli görev türleri oluşturacak ve hepsini polimorfik bir koleksiyon içinde birlikte işleyeceksiniz.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • task.go: Bir Summary() string metodu gerektiren bir Task arayüzü (interface) tanımlayın. Bu arayüz, tüm görev türlerinin yerine getirmesi gereken ortak sözleşme olacaktır.
  • types.go: Her biri Task arayüzünü uygulayan üç farklı görev türü oluşturun:
    • ID (string) ve Severity (string) alanlarına sahip BugFixSummary() metodu Bug #[ID] ([Severity]) değerini döndürür
    • Name (string) ve Points (int) alanlarına sahip FeatureSummary() metodu Feature: [Name] - [Points] pts değerini döndürür
    • Topic (string) alanına sahip DocumentationSummary() metodu Docs: [Topic] değerini döndürür
  • main.go: Bir Task dilimi (slice) kabul eden ve her görevin özetini kendi satırında yazdıran PrintBacklog adında bir fonksiyon oluşturun. Görev detaylarını girdiden okuyun, her görev türünden birer tane oluşturun, hepsini tek bir []Task diliminde toplayın ve bunu PrintBacklog fonksiyonuna gönderin.

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

  • Satır 1: Bug ID
  • Satır 2: Bug severity
  • Satır 3: Feature name
  • Satır 4: Feature points (tam sayı)
  • Satır 5: Documentation topic

Örneğin, 1042, critical, Dark Mode, 8 ve API Reference verildiğinde, çıktınız şu şekilde olmalıdır:

Bug #1042 (critical)
Feature: Dark Mode - 8 pts
Docs: API Reference

Buradaki güç, PrintBacklog fonksiyonunun hatalar, özellikler veya dokümantasyon için ayrı mantıklara ihtiyaç duymamasıdır; sadece dilim üzerinde döner ve her öğe üzerinde Summary() metodunu çağırır. Her görev türü kendi benzersiz formatıyla yanıt verir, bu da polimorfik koleksiyonların farklı türleri tek tipte işlemenize nasıl olanak tanıdığını gösterir.

Kopya kağıdı

Bir arayüz (interface) türündeki dilim (slice), o arayüzü karşılayan herhangi bir değeri tutabilir ve bu da polimorfik koleksiyonlara olanak tanır:

type Shape interface {
    Area() float64
}

type Circle struct{ Radius float64 }
func (c Circle) Area() float64 { return 3.14159 * c.Radius * c.Radius }

type Rectangle struct{ Width, Height float64 }
func (r Rectangle) Area() float64 { return r.Width * r.Height }

func main() {
    shapes := []Shape{
        Circle{Radius: 5},
        Rectangle{Width: 4, Height: 3},
        Circle{Radius: 2},
    }
    
    for _, s := range shapes {
        fmt.Printf("Area: %.2f\n", s.Area())
    }
}

shapes dilimi, her ikisi de Shape arayüzünü uygulayan farklı türleri (Circle ve Rectangle) tutar. Yineleme sırasında, her öğe kendi gerçek türüne göre Area() metoduna yanıt verir; bu, koleksiyonlara uygulanan polimorfizmdir.

Bu desen, çeşitli öğelerin tek tip bir şekilde işlenmesi için kullanışlıdır: farklı mesaj türlerini işleyen bildirim sistemleri, çeşitli düşman türlerini güncelleyen oyunlar veya birden fazla dosya formatını işleyen belge işlemcileri.

Kendin dene

package main

import (
	"fmt"
)

// TODO: Task dilimini (slice) kabul eden ve her bir görevin özetini
// kendi satırında yazdıran bir PrintBacklog fonksiyonu oluşturun

func main() {
	// Girdiyi oku
	var bugID string
	var bugSeverity string
	var featureName string
	var featurePoints int
	var docTopic string

	fmt.Scanln(&bugID)
	fmt.Scanln(&bugSeverity)
	fmt.Scanln(&featureName)
	fmt.Scanln(&featurePoints)
	fmt.Scanln(&docTopic)

	// TODO: Her görev türünden (BugFix, Feature, Documentation) birer tane oluşturun

	// TODO: Tüm görevleri tek bir []Task diliminde (slice) toplayın

	// TODO: Görev dilimi ile PrintBacklog fonksiyonunu çağırın
}
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