Metot Yükseltme
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 36 / 107.
Tıpkı struct gömmenin (embedding) alanları dış struct'a yükseltmesi gibi, Go gömülü türlerdeki metotları da yükseltir. Bu, gömülü struct üzerinde tanımlanan metotları doğrudan dış struct üzerinden çağırabileceğiniz anlamına gelir.
type Engine struct {
Horsepower int
}
func (e Engine) Start() string {
return "Engine started"
}
type Car struct {
Model string
Engine // gömülü
}
Car yapısı Engine yapısını gömdüğü için Start() metodu otomatik olarak üst seviyeye taşınır:
func main() {
c := Car{
Model: "Sedan",
Engine: Engine{Horsepower: 200},
}
fmt.Println(c.Start()) // Motor çalıştırıldı
fmt.Println(c.Engine.Start()) // bu da çalışır
}
Bu yükseltmenin (promotion) arayüzler için önemli bir sonucu vardır. Eğer gömülü tür bir arayüzü karşılıyorsa, dış tür de otomatik olarak o arayüzü karşılar:
type Starter interface {
Start() string
}
func Ignite(s Starter) {
fmt.Println(s.Start())
}
func main() {
c := Car{Model: "Sedan", Engine: Engine{Horsepower: 200}}
Ignite(c) // Car, Engine aracılığıyla Starter arayüzünü karşılar
}
Car tipi hiçbir zaman açıkça Starter arayüzünü uygulamaz, ancak gömülü Engine gerekli metoda sahip olduğu için arayüzü karşılar. Go, geleneksel kalıtım olmadan davranışın yeniden kullanımını bu şekilde gerçekleştirir.
Görev
KolayGömülü türlerdeki metotların dış türe nasıl aktarıldığını ve bunun kompozisyon yoluyla arayüz (interface) uyumluluğunu nasıl sağladığını gösteren bir müzik çalar sistemi oluşturalım.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
audio.go: Müzik çalarınız için temel yapı taşlarını oluşturun:Brandalanına (string) ve[Brand] playing audiodeğerini döndüren birPlay() stringmetoduna sahip birAudioPlayeryapısı (struct).Play() stringmetodu gerektiren birPlayablearayüzü (interface).AudioPlayeryapısını gömen (embed),Modelalanına sahip birSmartphoneyapısı.AudioPlayeryapısını gömen (embed),Modelalanına sahip birTabletyapısı.
main.go: Herhangi birPlayablekabul eden vePlay()metodunu çağırmanın sonucunu döndürenStartPlaybackadında bir fonksiyon oluşturun. Girişten cihaz bilgilerini okuyun, hem bir Smartphone hem de bir Tablet oluşturun ve her iki türün dePlay()metodunu açıkça uygulamamasına rağmen, gömülüAudioPlayeraracılığıylaPlayablearayüzünü nasıl karşıladığını gösterin.
Aşağıdaki girişler sağlanacaktır:
- Satır 1: Akıllı telefon model adı
- Satır 2: Akıllı telefon ses markası
- Satır 3: Tablet model adı
- Satır 4: Tablet ses markası
Her cihaz için, önce modelini, ardından cihazı StartPlayback fonksiyonuna göndermenin sonucunu yazdırın.
Örneğin, iPhone 15, Apple Audio, iPad Pro ve Beats verildiğinde çıktınız şu şekilde olmalıdır:
iPhone 15
Apple Audio playing audio
iPad Pro
Beats playing audioAudioPlayer içindeki Play() metodunun otomatik olarak her bir dış türe aktarılması sayesinde, hem Smartphone hem de Tablet yapılarının herhangi bir ek kod yazılmadan Playable arayüzünü nasıl karşıladığına ve StartPlayback fonksiyonuna nasıl gönderilebildiğine dikkat edin.
Kopya kağıdı
Bir struct başka bir türü gömdüğünde, gömülü türdeki metotlar otomatik olarak dıştaki struct'a aktarılır (promoted):
type Engine struct {
Horsepower int
}
func (e Engine) Start() string {
return "Engine started"
}
type Car struct {
Model string
Engine // gömülü
}
func main() {
c := Car{
Model: "Sedan",
Engine: Engine{Horsepower: 200},
}
fmt.Println(c.Start()) // Engine started
fmt.Println(c.Engine.Start()) // bu da çalışır
}
Eğer gömülü bir tür bir arayüzü (interface) karşılıyorsa, dıştaki tür de otomatik olarak onu karşılar:
type Starter interface {
Start() string
}
func Ignite(s Starter) {
fmt.Println(s.Start())
}
func main() {
c := Car{Model: "Sedan", Engine: Engine{Horsepower: 200}}
Ignite(c) // Car, Engine aracılığıyla Starter arayüzünü karşılar
}
Bu, geleneksel kalıtım olmadan kompozisyon (composition) yoluyla davranışın yeniden kullanılmasını sağlar.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
)
// TODO: Herhangi bir Playable kabul eden bir StartPlayback fonksiyonu oluşturun
// ve Play() çağrısının sonucunu döndürün
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Akıllı telefon modelini oku
scanner.Scan()
smartphoneModel := scanner.Text()
// Akıllı telefon ses markasını oku
scanner.Scan()
smartphoneBrand := scanner.Text()
// Tablet modelini oku
scanner.Scan()
tabletModel := scanner.Text()
// Tablet ses markasını oku
scanner.Scan()
tabletBrand := scanner.Text()
// TODO: Gömülü AudioPlayer ile bir Smartphone oluşturun
// TODO: Gömülü AudioPlayer ile bir Tablet oluşturun
// TODO: Akıllı telefon modelini yazdırın, ardından akıllı telefon ile StartPlayback fonksiyonunu çağırın
// TODO: Tablet modelini yazdırın, ardından tablet ile StartPlayback fonksiyonunu çağırın
_ = smartphoneModel
_ = smartphoneBrand
_ = tabletModel
_ = tabletBrand
fmt.Println("TODO: Complete the implementation")
}
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 Pool