Menu
Coddy logo textTech

Gömülü Metotları Gölgeleme

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

Bazen dış yapının (outer struct), gömülü türün (embedded type) halihazırda sahip olduğu bir metodun kendi uygulamasını sağlamasına ihtiyaç duyarsınız. Buna shadowing (gölgeleme) denir ve yükseltilmiş metodları (promoted methods) özel davranışlarla geçersiz kılmanıza (override) olanak tanır.

Dış yapı (struct) üzerinde, gömülü bir metotla aynı ada sahip bir metot tanımladığınızda, dış metot öncelik kazanır:

type Animal struct {
    Name string
}

func (a Animal) Speak() string {
    return "Some sound"
}

type Dog struct {
    Animal
    Breed string
}

func (d Dog) Speak() string {
    return "Woof!"
}

Artık bir Dog üzerinde Speak() metodunu çağırdığınızda, dıştaki metot kullanılır:

func main() {
    d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Labrador"}
    
    fmt.Println(d.Speak())        // Hav! - Dog'un metodu
    fmt.Println(d.Animal.Speak()) // Bir ses - Animal'ın metodu
}

Gömülü (embedded) metot kaybolmaz. Gömülü tür adı aracılığıyla ona hala açıkça erişebilirsiniz. Bu desen, orijinal uygulamayı kullanılabilir tutarken davranışı özelleştirmek istediğinizde, belki de onu geçersiz kılan (overriding) metodunuzun içinden çağırmak için kullanışlıdır:

func (d Dog) Speak() string {
    return d.Animal.Speak() + " (but actually Woof!)"
}

Gölgeleme, açık niteleme yoluyla orijinaline erişimi korurken, hangi davranışın sergileneceği üzerinde size kontrol sağlar.

challenge icon

Görev

Kolay

Farklı bildirim kanallarının mesajları nasıl biçimlendireceğini ve ileteceğini özelleştirebildiği bir bildirim sistemi oluşturalım. Belirli kanalların varsayılan davranışı geçersiz kılmasına (override) izin vermek ve gerektiğinde orijinal uygulamaya hala erişebilmek için metot gölgeleme (method shadowing) kullanacaksınız.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • base.go: Title ve Priority alanlarına (her ikisi de string) sahip bir BaseNotification yapısı oluşturun. Buna, bildirimi standart bir biçimde döndüren bir Format() string metodu verin: [Priority] Title.
  • channels.go: BaseNotification yapısını gömen (embed) ve Format metodunu kendi uygulamalarıyla gölgeleyen iki bildirim kanalı türü oluşturun:
    • Recipient alanına sahip EmailNotificationFormat() metodu Email to [Recipient]: [Priority] Title döndürmelidir.
    • Channel alanına sahip SlackNotificationFormat() metodu, gömülü olan BaseNotification.Format() metodunu çağırmalı ve sonucun başına #[Channel]: eklemelidir.
  • main.go: Girdiden bildirim ayrıntılarını okuyun, her iki bildirim türünü de oluşturun ve şunları yazdırarak gölgelemeyi gösterin:
    1. EmailNotification'ın biçimlendirilmiş çıktısı (kendi gölgelenmiş metodunu kullanarak)
    2. EmailNotification'ın temel biçimi (gömülü metodu açıkça çağırarak)
    3. SlackNotification'ın biçimlendirilmiş çıktısı (dahili olarak temel metodu kullanan)

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

  • Satır 1: Bildirim başlığı
  • Satır 2: Öncelik seviyesi
  • Satır 3: E-posta alıcısı
  • Satır 4: Slack kanal adı

Örneğin, Server Alert, HIGH, admin@company.com ve ops-alerts verildiğinde, çıktınız şöyle olmalıdır:

Email to admin@company.com: HIGH Server Alert
[HIGH] Server Alert
#ops-alerts: [HIGH] Server Alert

EmailNotification'ın temel biçimlendirmeyi tamamen nasıl değiştirdiğine, SlackNotification'ın ise orijinal metodu çağırıp kanal bağlamı ekleyerek onu nasıl geliştirdiğine dikkat edin. Her iki yaklaşım da metot gölgelemenin etkili bir şekilde kullanılmasının farklı yollarını göstermektedir.

Kopya kağıdı

Dış bir struct üzerinde, gömülü bir türdeki metotla aynı isme sahip bir metot tanımladığınızda, dıştaki metot gömülü metodu gölgeler (geçersiz kılar):

type Animal struct {
    Name string
}

func (a Animal) Speak() string {
    return "Some sound"
}

type Dog struct {
    Animal
    Breed string
}

func (d Dog) Speak() string {
    return "Woof!"
}

Dış struct üzerindeki metodu çağırırken, dıştaki metot öncelik kazanır:

d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Labrador"}

fmt.Println(d.Speak())        // Woof! - Dog'un metodu
fmt.Println(d.Animal.Speak()) // Some sound - Animal'ın metodu

Gömülü metot, gömülü tür adı kullanılarak açıkça belirtilerek erişilebilir kalmaya devam eder. Orijinal uygulamayı, geçersiz kılan metodun içinden çağırabilirsiniz:

func (d Dog) Speak() string {
    return d.Animal.Speak() + " (but actually Woof!)"
}

Kendin dene

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Bildirim başlığını oku
	scanner.Scan()
	title := scanner.Text()
	
	// Öncelik seviyesini oku
	scanner.Scan()
	priority := scanner.Text()
	
	// E-posta alıcısını oku
	scanner.Scan()
	recipient := scanner.Text()
	
	// Slack kanal adını oku
	scanner.Scan()
	channel := scanner.Text()
	
	// TODO: Temel bildirim, başlık, öncelik ve alıcı ile bir EmailNotification oluşturun
	
	// TODO: Temel bildirim, başlık, öncelik ve kanal ile bir SlackNotification oluşturun
	
	// TODO: EmailNotification'ın biçimlendirilmiş çıktısını yazdırın (gölgelenmiş yöntemini kullanarak)
	
	// TODO: EmailNotification'ın temel biçimini yazdırın (gömülü yöntemi açıkça çağırarak)
	
	// TODO: SlackNotification'ın biçimlendirilmiş çıktısını yazdırın
	
	fmt.Println() // Yer tutucu - uygularken kaldı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