Duck Typing di Go
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 42 dari 107.
Istilah duck typing berasal dari ungkapan: "Jika ia berjalan seperti bebek dan bersuara seperti bebek, maka ia adalah bebek." Dalam Go, ini berarti tipe tidak perlu secara eksplisit menyatakan bahwa tipe tersebut mengimplementasikan interface. Tipe itu hanya perlu memiliki method yang tepat.
Perhatikan interface ini dan dua tipe yang sama sekali tidak berkaitan:
type Quacker interface {
Quack() string
}
type Duck struct{}
func (d Duck) Quack() string { return "Quack!" }
type Robot struct{}
func (r Robot) Quack() string { return "Beep-quack!" }
Baik Duck maupun Robot tidak menyebutkan Quacker di mana pun dalam definisinya. Namun, keduanya memenuhi antarmuka hanya karena memiliki method Quack() dengan tanda tangan yang tepat:
func MakeItQuack(q Quacker) {
fmt.Println(q.Quack())
}
func main() {
MakeItQuack(Duck{}) // Quack!
MakeItQuack(Robot{}) // Beep-quack!
}
Kesesuaian implisit ini sangat berguna karena memungkinkan kamu mendefinisikan interface setelah tipe-tipe tersebut sudah ada. Kamu bisa membuat interface yang cocok dengan tipe dari package eksternal tanpa mengubah kode sumbernya. Tipe-tipe tersebut tidak perlu mengetahui interface-mu. Tipe-tipe itu hanya perlu berperilaku dengan benar.
Duck typing di Go memberimu fleksibilitas seperti pada bahasa dinamis sekaligus mempertahankan keamanan tipe saat kompilasi. Kompilator memverifikasi bahwa tipe benar-benar memiliki method yang diperlukan sebelum mengizinkannya digunakan sebagai nilai interface.
Tantangan
MudahMari buat sistem pesan yang menunjukkan duck typing dalam praktik. Kamu akan membuat tipe-tipe yang sama sekali tidak berhubungan, tetapi semuanya dapat mengirim pesan melalui antarmuka yang sama, tanpa secara eksplisit menyatakan bahwa mereka mengimplementasikannya.
Kamu akan membagi kodemu ke dalam tiga file:
messengers.go: Buat tiga struct yang tidak berhubungan, tetapi memiliki perilaku yang sama:Phonedengan fieldNumber. methodSendMessage(text string) string-nya mengembalikanSMS to [Number]: [text]Computerdengan fieldEmail. methodSendMessage(text string) string-nya mengembalikanEmail to [Email]: [text]Pigeondengan fieldName. methodSendMessage(text string) string-nya mengembalikan[Name] carries: [text]
sender.go: Definisikan antarmukaMessengeryang memerlukan methodSendMessage(text string) string. Buat fungsi bernamaBroadcastyang menerima slice berisiMessengerdan string pesan, lalu mengembalikan slice berisi string yang memuat hasil pemanggilanSendMessagepada setiap messenger.main.go: Baca detail dari input, buat masing-masing satu dari setiap tipe messenger, kumpulkan semuanya ke dalam slice berisiMessenger, lalu gunakanBroadcastuntuk mengirim pesan melalui semuanya. Cetak setiap hasil pada barisnya sendiri.
Input berikut akan diberikan:
- Baris 1: Nomor telepon
- Baris 2: Alamat email
- Baris 3: Nama merpati
- Baris 4: Pesan untuk disebarkan
Misalnya, jika diberikan 555-1234, alice@mail.com, Winston, dan Hello World, output-mu seharusnya:
SMS to 555-1234: Hello World
Email to alice@mail.com: Hello World
Winston carries: Hello WorldInti utamanya adalah Phone, Computer, dan Pigeon tidak memiliki kesamaan. Mereka tidak berbagi tipe dasar atau secara eksplisit mengimplementasikan Messenger. Namun, karena semuanya "berkwek" dengan cara yang sama (memiliki method yang cocok), Go memungkinkan semuanya digunakan sebagai nilai Messenger. Inilah duck typing dalam praktik.
Coba sendiri
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Baca nomor telepon
scanner.Scan()
phoneNumber := scanner.Text()
// Baca alamat email
scanner.Scan()
email := scanner.Text()
// Baca nama merpati
scanner.Scan()
pigeonName := scanner.Text()
// Baca pesan untuk disiarkan
scanner.Scan()
message := scanner.Text()
// TODO: Buat satu dari setiap tipe pengirim pesan (Phone, Computer, Pigeon)
// TODO: Kumpulkan semua pengirim pesan ke dalam slice bertipe Messenger
// TODO: Gunakan Broadcast untuk mengirim pesan melalui semua pengirim pesan
// TODO: Cetak setiap hasil pada baris tersendiri
// Penampung sementara untuk menggunakan variabel (hapus saat kamu mengimplementasikannya)
_ = phoneNumber
_ = email
_ = pigeonName
_ = message
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online