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 depolamaktır. Bir arayüz türünün dilimi, o arayüzü karşılayan herhangi bir değeri tutabilir ve ilgili ancak farklı türleri birlikte gruplandırmanı sağlar.
Çeşitli şekilleri yönetmeniz gereken bir senaryoyu 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. Yineleme sırasında her öğe, gerçek türüne göre Area() yanıtını verir. Bu, koleksiyonlara uygulanan çok biçimliliktir: aynı döngü, tüm şekil türlerini tekdüze bir şekilde işler.
Polimorfik koleksiyonlar, çeşitli öğeleri işleyen sistemler oluştururken gereklidir: e-posta 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. Koleksiyon belirli türlerle ilgilenmez: yalnızca her öğenin gerekli davranışı sağlaması yeterlidir.
Görev
KolayBirleşik bir arayüz üzerinden farklı görev türlerini işleyen 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 ayıracaksın:
task.go:Taskmetodunu gerektiren birSummary() stringarayüzü tanımla. Bu arayüz, tüm görev türlerinin karşılaması gereken ortak sözleşme olacaktır.types.go:Taskarayüzünü uygulayan üç farklı görev türü oluştur:BugFix;ID(string) veSeverity(string) alanlarına sahip olsun.Summary()metoduBug #[ID] ([Severity])döndürür.Feature;Name(string) vePoints(int) alanlarına sahip olsun.Summary()metoduFeature: [Name] - [Points] ptsdöndürür.Documentation;Topic(string) alanına sahip olsun.Summary()metoduDocs: [Topic]döndürür.
main.go:PrintBacklogdilimünü kabul eden ve her görevin özetini kendi satırında yazdıranTaskadlı bir fonksiyon 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 dilimiPrintBacklogfonksiyonuna aktar.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Hata kimliği
- 2. satır: Hata önem derecesi
- 3. satır: Özellik adı
- 4. satır: Özellik puanı (tam sayı)
- 5. satır: Dokümantasyon konusu
Örneğin 1042, critical, Dark Mode, 8 ve API Reference verildiğinde çıktın şöyle olmalıdır:
Bug #1042 (critical)
Feature: Dark Mode - 8 pts
Docs: API ReferenceBuradaki güç, PrintBacklog fonksiyonunun hatalar, özellikler veya dokümantasyon için ayrı bir mantığa ihtiyaç duymamasıdır. Fonksiyon, dilim üzerinde yineleme yapar ve her öğe için Summary() metodunu çağırır. Her görev türü kendi benzersiz biçimiyle yanıt verir; bu da polimorfik koleksiyonların farklı türleri tekdüze biçimde işlemeni nasıl sağladığını gösterir.
Kendin dene
package main
import (
"fmt"
)
// TODO: Task dilimini kabul eden bir PrintBacklog fonksiyonu oluştur
// ve her görevin özetini kendi satırına yazdırı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 bir tane oluştur (BugFix, Feature, Documentation)
// TODO: Tüm görevleri tek bir []Task diliminde topla
// TODO: PrintBacklog'u görev dilimiyle ç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