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ü kullanım alanlarından biri, aynı koleksiyonda farklı türleri saklamaktır. Bir arayüz türünden dilim, o arayüzü karşılayan herhangi bir değeri tutabilir; böylece birbiriyle ilişkili ancak farklı türleri birlikte gruplayabilirsin.
Çeşitli şekilleri yönetmeniz gereken bir senaryo düşünün. Her tür için ayrı dilimler kullanmak yerine, arayüz türünden 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 içerir. Döngüde gezinirken her öğe, gerçek türüne göre Area() çağrısına yanıt verir. Bu, koleksiyonlara uygulanan çok biçimliliktir: aynı döngü tüm şekil türlerini tutarlı bir şekilde işler.
Polimorfik koleksiyonlar; e-postalar ve SMS mesajları gönderen bir bildirim sistemi, farklı düşman türlerini güncelleyen bir oyun veya birden çok dosya biçimini işleyen bir belge işlemcisi gibi çeşitli öğeleri işleyen sistemler oluştururken vazgeçilmezdir. Koleksiyon belirli türleri önemsemez; yalnızca her öğenin gerekli davranışı sağlaması gerekir.
Görev
KolayFarklı 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 bunların tümünü polimorfik bir koleksiyonda birlikte işleyeceksin.
Kodunu üç dosyaya dağıtacaksın:
task.go:Summary() stringyöntemini gerektiren birTaskarayüzü tanımla. Bu arayüz, tüm görev türlerinin yerine getirmesi gereken ortak sözleşme olacak.types.go: Her biriTaskarayüzünü uygulayan üç farklı görev türü oluştur:BugFix;ID(string) veSeverity(string) alanlarına sahip.Summary()yöntemiBug #[ID] ([Severity])döndürür.Feature;Name(string) vePoints(int) alanlarına sahip.Summary()yöntemiFeature: [Name] - [Points] ptsdöndürür.Documentation;Topic(string) alanına sahip.Summary()yöntemiDocs: [Topic]döndürür.
main.go: BirTaskdilimini kabul eden ve her görevin özetini ayrı bir satıra yazdıranPrintBacklogadlı bir işlev oluştur. Görev ayrıntılarını girdiden oku, her görev türünden bir tane oluştur, hepsini tek bir[]Taskdiliminde topla ve bu dilimiPrintBacklogişlevine gönder.
Aşağıdaki girdiler sağlanacak:
- 1. satır: Hata kimliği
- 2. satır: Hatanın önem derecesi
- 3. satır: Özellik adı
- 4. satır: Özellik puanı (tam sayı)
- 5. satır: Dokümantasyon konusu
Örneğin, 1042, critical, Themes, 8 ve API verildiğinde çıktın şöyle olmalı:
Bug #1042 (critical)
Feature: Themes - 8 pts
Docs: APIBuradaki güç, PrintBacklog işlevinin hatalar, özellikler veya dokümantasyon için ayrı bir mantığa ihtiyaç duymamasıdır. İşlev yalnızca dilim üzerinde yineleme yapar ve her öğenin Summary() yöntemini çağırır. Her görev türü kendine özgü bir biçimde yanıt vererek polimorfik koleksiyonların farklı türleri nasıl aynı şekilde işlemene olanak tanıdığını gösterir.
Kendin dene
package main
import (
"fmt"
)
// TODO: Task türünden bir dilim kabul eden bir PrintBacklog fonksiyonu oluştur
// ve her görevin özetini ayrı bir satıra yazdır
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ştur
// TODO: Tüm görevleri tek bir []Task diliminde topla
// TODO: PrintBacklog fonksiyonunu görevlerin bulunduğu dilimle çağır
}
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