Menu
Coddy logo textTech

Örtük Uygulama

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

Java veya C# gibi birçok nesne yönelimli dilde, implements gibi anahtar kelimeler kullanarak bir türün bir arayüzü uyguladığını açıkça belirtmeniz gerekir. Go farklı bir yaklaşım benimser: arayüz uygulaması örtüktür (implicit).

Bir tür, sadece tüm metotlarını uygulayarak bir arayüzü karşılar. İlişkiyi herhangi bir yerde beyan etmeye gerek yoktur. Derleyici bunu otomatik olarak anlar.

type Writer interface {
    Write(data string) int
}

type FileWriter struct {
    Filename string
}

// FileWriter, Writer arayüzünü örtük olarak uygular
func (f FileWriter) Write(data string) int {
    fmt.Println("Writing to", f.Filename)
    return len(data)
}

FileWriter üzerinde implements Writer bildirimi olmadığına dikkat edin. FileWriter, arayüz imzasıyla eşleşen bir Write(data string) int metoduna sahip olduğu için, otomatik olarak Writer arayüzünü karşılar.

Bu tasarımın güçlü bir sonucu vardır: arayüzleri türler zaten mevcut olduktan sonra tanımlayabilirsiniz. Eğer üçüncü taraf bir kütüphanenin ihtiyacınız olan metotlara sahip bir türü varsa, orijinal kodu değiştirmeden, bu türün halihazırda karşıladığı bir arayüz oluşturabilirsiniz.

func Save(w Writer, content string) {
    w.Write(content)
}

func main() {
    fw := FileWriter{Filename: "data.txt"}
    Save(fw, "Hello!")  // FileWriter, Writer arayüzünü karşıladığı için çalışır
}

Örtük uygulama, Go kodunu ayrık ve esnek tutar. Türlerin arayüzler hakkında önceden bilgi sahibi olması gerekmez, bu da sistemleri bağımsız parçalardan oluşturmayı kolaylaştırır.

challenge icon

Görev

Kolay

Go'de türlerin arayüzleri (interfaces) nasıl örtük olarak (implicitly) karşıladığını gösteren bir mesaj teslimat sistemi kuralım. Herhangi bir ilişkiyi açıkça belirtmeden, aynı arayüzü karşılayan farklı haberci (messenger) türleri oluşturacaksınız.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • messengers.go: Tek bir Send(message string) string metoduna sahip bir Messenger arayüzü tanımlayın. Ardından bu arayüzü örtük olarak karşılayacak iki yapı (struct) oluşturun:
    • Address alanına (string) sahip EmailMessenger
    • PhoneNumber alanına (string) sahip SMSMessenger
    Her yapı, teslimatı açıklayan bir dize döndüren bir Send metoduna sahip olmalıdır. Hiçbir yapı Messenger arayüzünü uyguladığını açıkça beyan etmemelidir; Go, metod imzalarına dayanarak bunu otomatik olarak anlayacaktır.
  • main.go: Herhangi bir Messenger ve bir mesaj dizesi kabul eden, ardından Send metodunu çağırmanın sonucunu döndüren DeliverMessage adında bir fonksiyon oluşturun. Girişten iletişim bilgilerini okuyun, her iki haberci türünü de oluşturun ve her biri aracılığıyla mesajları iletmek için fonksiyonunuzu kullanın.

Aşağıdaki girişler sağlanacaktır:

  • Satır 1: E-posta adresi
  • Satır 2: Telefon numarası
  • Satır 3: Gönderilecek mesaj

Send metodlarınız şu formatlarda dizeler döndürmelidir:

  • EmailMessenger: Email to [Address]: [message]
  • SMSMessenger: SMS to [PhoneNumber]: [message]

Örneğin, alice@example.com, 555-1234 ve Hello! verildiğinde, çıktınız şu şekilde olmalıdır:

Email to alice@example.com: Hello!
SMS to 555-1234: Hello!

Buradaki temel nokta, DeliverMessage fonksiyonunuzun herhangi bir Messenger kabul etmesi ve hem EmailMessenger hem de SMSMessenger yapılarının sadece eşleşen bir Send metoduna sahip olarak bu arayüzü karşılamasıdır. Hiçbir yerde implements anahtar kelimesi yoktur; Go'nun örtük uygulaması (implicit implementation) her şeyi halleder.

Kopya kağıdı

Go'da arayüz (interface) uygulaması örtüktür (implicit). Bir tür, yalnızca tüm metodlarını uygulayarak bir arayüzü karşılar; açık bir bildirime gerek yoktur.

type Writer interface {
    Write(data string) int
}

type FileWriter struct {
    Filename string
}

// FileWriter örtük olarak Writer'ı uygular
func (f FileWriter) Write(data string) int {
    fmt.Println("Writing to", f.Filename)
    return len(data)
}

Herhangi bir implements Writer bildirimi yoktur. FileWriter, arayüz imzasıyla eşleşen bir Write(data string) int metoduna sahip olduğu için Writer arayüzünü otomatik olarak karşılar.

Bir arayüzü karşılayan herhangi bir türü, türün arayüzden haberi olmasına gerek kalmadan kullanabilirsiniz:

func Save(w Writer, content string) {
    w.Write(content)
}

func main() {
    fw := FileWriter{Filename: "data.txt"}
    Save(fw, "Hello!")  // FileWriter, Writer'ı karşıladığı için çalışır
}

Bu tasarım, türler zaten mevcut olduktan sonra arayüzler tanımlamanıza olanak tanıyarak kodun bağımsız (decoupled) ve esnek olmasını sağlar.

Kendin dene

package main

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

// YAPILACAK: Herhangi bir Messenger'ı ve bir mesaj dizesini kabul eden,
// ardından Send çağrısının sonucunu döndüren bir DeliverMessage fonksiyonu oluşturun

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// E-posta adresini oku
	email, _ := reader.ReadString('\n')
	email = email[:len(email)-1]
	
	// Telefon numarasını oku
	phone, _ := reader.ReadString('\n')
	phone = phone[:len(phone)-1]
	
	// Mesajı oku
	message, _ := reader.ReadString('\n')
	if len(message) > 0 && message[len(message)-1] == '\n' {
		message = message[:len(message)-1]
	}
	
	// YAPILACAK: E-posta adresiyle bir EmailMessenger oluşturun
	
	// YAPILACAK: Telefon numarasıyla bir SMSMessenger oluşturun
	
	// YAPILACAK: Mesajı her bir messenger aracılığıyla göndermek için DeliverMessage'ı kullanın
	// ve sonuçları yazdı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