Arayüz Bileşimi
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 31 / 107.
Go, daha küçük arayüzleri birleştirerek daha büyük arayüzler inşa etmenize olanak tanır. Birçok metoda sahip tek bir büyük arayüz tanımlamak yerine, mevcut arayüzleri yeni bir arayüz tanımının içine gömersiniz.
type Reader interface {
Read() string
}
type Writer interface {
Write(data string)
}
// ReadWriter her iki arayüzü birleştirir
type ReadWriter interface {
Reader
Writer
}ReadWriter arayüzü artık hem Read() hem de Write() metotlarını gerektiriyor. Her iki metodu da uygulayan herhangi bir tür, ReadWriter arayüzünün yanı sıra ayrı ayrı Reader ve Writer arayüzlerini de karşılar.
type File struct {
Name string
}
func (f File) Read() string { return "file content" }
func (f File) Write(data string) { fmt.Println("Writing:", data) }
func Process(rw ReadWriter) {
content := rw.Read()
rw.Write(content)
}
func main() {
f := File{Name: "data.txt"}
Process(f) // File, ReadWriter arayüzünü sağlar
}Bu bileşim yaklaşımı, arayüzleri küçük ve odaklanmış tutar. İhtiyaca göre bunları karıştırıp eşleştirebilir, fonksiyonlarınız için kesin sözleşmeler oluşturabilirsiniz. Go'nun standart kütüphanesi, io.Reader ve io.Writer'ı birleştiren io.ReadWriter gibi bu deseni yaygın olarak kullanır.
Görev
KolayArayüz bileşimini (interface composition) gösteren bir medya oynatıcı sistemi oluşturalım. Küçük, odaklanmış arayüzler oluşturacak ve ardından bunları tek bir türün karşılayabileceği daha güçlü, birleşik bir arayüzde birleştireceksiniz.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
media.go: Üç arayüz ve bunların hepsini uygulayan bir struct tanımlayın:Play() stringmetoduna sahip birPlayerarayüzüRecord(content string) stringmetoduna sahip birRecorderarayüzü- Hem
Playerhem deRecorderarayüzlerini birleştiren birMediaDevicearayüzü - Gerekli tüm metodları uygulayan,
Namealanına sahip birSmartDevicestruct'ı
main.go: AynıSmartDeviceyapısının farklı arayüz türleri üzerinden nasıl kullanılabileceğini gösteren fonksiyonlar oluşturun. Üç fonksiyon yazın:- Bir
Playerkabul eden ve onunPlaymetodunu çağıranUsePlayer - Bir
Recorderve bir içerik dizesi kabul eden, ardındanRecordmetodunu çağıranUseRecorder - Bir
MediaDeviceve bir içerik dizesi kabul eden, ardından hemRecordhem dePlaymetodlarını çağıranUseMediaDevice
SmartDeviceoluşturun ve onu her üç arayüz türü üzerinden kullanmayı gösterin.- Bir
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Cihaz adı
- Satır 2: Kaydedilecek içerik
Metodlarınız şu formatlarda dizeler döndürmelidir:
Play():[Name] is playingRecord(content):[Name] recorded: [content]
Örneğin, MyPhone ve voice memo verildiğinde, çıktınız şu şekilde olmalıdır:
MyPhone is playing
MyPhone recorded: voice memo
MyPhone recorded: voice memo
MyPhone is playingİlk iki satır, cihazın bireysel arayüzler (Player ve Recorder) aracılığıyla kullanımını gösterir. Son iki satır ise her iki yeteneği de gerektiren birleşik MediaDevice arayüzü aracılığıyla kullanımını gösterir. Tek bir SmartDevice yapısının, gerekli her iki metoda da sahip olduğu için her üç arayüzü de nasıl karşıladığına dikkat edin.
Kopya kağıdı
Go, mevcut arayüzleri yeni bir arayüz tanımı içine gömerek daha küçük olanları birleştirerek (composing) daha büyük arayüzler oluşturmanıza olanak tanır:
type Reader interface {
Read() string
}
type Writer interface {
Write(data string)
}
// ReadWriter her iki arayüzü birleştirir
type ReadWriter interface {
Reader
Writer
}Gömülü arayüzlerdeki tüm metotları uygulayan herhangi bir tür, birleştirilmiş arayüzü karşılar:
type File struct {
Name string
}
func (f File) Read() string { return "file content" }
func (f File) Write(data string) { fmt.Println("Writing:", data) }
func Process(rw ReadWriter) {
content := rw.Read()
rw.Write(content)
}
func main() {
f := File{Name: "data.txt"}
Process(f) // File, ReadWriter arayüzünü karşılar
}Birleştirilmiş bir arayüzü uygulayan bir tür, aynı zamanda gömülü olan her bir arayüzü de karşılar. Bu birleştirme yaklaşımı, arayüzleri küçük ve odaklanmış tutarken fonksiyonlarınız için kesin sözleşmeler oluşturmanıza olanak tanır.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
)
// TODO: Bir Player kabul eden ve onun Play metodunu çağıran UsePlayer fonksiyonunu uygulayın
// Play() metodunun sonucunu yazdırmalıdır
// TODO: Bir Recorder ve bir içerik dizesi kabul eden UseRecorder fonksiyonunu uygulayın
// Record(content) metodunun sonucunu yazdırmalıdır
// TODO: Bir MediaDevice ve bir içerik dizesi kabul eden UseMediaDevice fonksiyonunu uygulayın
// Record(content) ve ardından Play() metodunun sonucunu yazdırmalıdır
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
deviceName := scanner.Text()
scanner.Scan()
content := scanner.Text()
// TODO: Verilen isimle bir SmartDevice oluşturun
// TODO: Cihazı Player arayüzü üzerinden kullanın
// TODO: Cihazı Recorder arayüzü üzerinden kullanın
// TODO: Cihazı MediaDevice arayüzü üzerinden kullanın
_ = deviceName
_ = content
fmt.Println("Implement the solution")
}
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