Koleksi Polimorfik
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 44 dari 107.
Salah satu penerapan interface yang paling bermanfaat adalah menyimpan berbagai tipe dalam koleksi yang sama. Slice dengan tipe interface dapat menampung nilai apa pun yang memenuhi interface tersebut, sehingga kamu dapat mengelompokkan tipe yang berkaitan tetapi berbeda.
Bayangkan sebuah skenario ketika kamu perlu mengelola berbagai bentuk. Daripada menggunakan slice terpisah untuk setiap jenis, kamu bisa menggunakan satu slice dengan tipe interface:
type Shape interface {
Area() float64
}
type Circle struct{ Radius float64 }
func (c Circle) Area() float64 { return 3.14159 * c.Radius * c.Radius }
type Rectangle struct{ Width, Height float64 }
func (r Rectangle) Area() float64 { return r.Width * r.Height }
func main() {
shapes := []Shape{
Circle{Radius: 5},
Rectangle{Width: 4, Height: 3},
Circle{Radius: 2},
}
for _, s := range shapes {
fmt.Printf("Area: %.2f\n", s.Area())
}
}
Slice shapes menyimpan lingkaran dan persegi panjang. Saat melakukan iterasi, setiap elemen merespons Area() sesuai dengan tipe sebenarnya. Inilah polimorfisme yang diterapkan pada koleksi: perulangan yang sama menangani semua tipe bentuk secara seragam.
Koleksi polimorfik sangat penting saat membangun sistem yang memproses berbagai item: sistem notifikasi yang mengirim email dan pesan SMS, game yang memperbarui berbagai tipe musuh, atau pemroses dokumen yang menangani beberapa format file. Koleksi ini tidak memedulikan tipe tertentu, yang penting setiap elemen menyediakan perilaku yang dibutuhkan.
Tantangan
MudahMari kita bangun sistem manajemen tugas yang menangani berbagai jenis tugas melalui antarmuka terpadu. Kamu akan membuat berbagai jenis tugas dan memproses semuanya bersama-sama dalam sebuah koleksi polimorfik.
Kamu akan mengatur kodemu dalam tiga file:
task.go: Definisikan antarmukaTaskyang mewajibkan methodSummary() string. Antarmuka ini akan menjadi kontrak umum yang harus dipenuhi oleh semua jenis tugas.types.go: Buat tiga jenis tugas berbeda yang masing-masing mengimplementasikan antarmukaTask:BugFixdengan fieldID(string) danSeverity(string).Summary()miliknya mengembalikanBug #[ID] ([Severity])Featuredengan fieldName(string) danPoints(int).Summary()miliknya mengembalikanFeature: [Name] - [Points] ptsDocumentationdengan fieldTopic(string).Summary()miliknya mengembalikanDocs: [Topic]
main.go: Buat fungsi bernamaPrintBacklogyang menerima sliceTaskdan mencetak ringkasan setiap tugas pada barisnya sendiri. Baca detail tugas dari input, buat masing-masing satu jenis tugas, kumpulkan semuanya ke dalam satu slice[]Task, lalu berikan slice itu kePrintBacklog.
Input berikut akan diberikan:
- Baris 1: ID bug
- Baris 2: Tingkat keparahan bug
- Baris 3: Nama fitur
- Baris 4: Poin fitur (bilangan bulat)
- Baris 5: Topik dokumentasi
Misalnya, jika diberikan 1042, critical, Dark Mode, 8, dan API Reference, outputmu seharusnya:
Bug #1042 (critical)
Feature: Dark Mode - 8 pts
Docs: API ReferenceKeunggulannya adalah PrintBacklog tidak memerlukan logika terpisah untuk bug, fitur, atau dokumentasi. Fungsi ini cukup mengiterasi slice dan memanggil Summary() pada setiap elemennya. Setiap jenis tugas merespons dengan format uniknya sendiri, yang menunjukkan bagaimana koleksi polimorfik memungkinkanmu memproses beragam jenis secara seragam.
Coba sendiri
package main
import (
"fmt"
)
// TODO: Buat fungsi PrintBacklog yang menerima slice berisi Task
// dan mencetak ringkasan setiap tugas pada baris tersendiri
func main() {
// Baca input
var bugID string
var bugSeverity string
var featureName string
var featurePoints int
var docTopic string
fmt.Scanln(&bugID)
fmt.Scanln(&bugSeverity)
fmt.Scanln(&featureName)
fmt.Scanln(&featurePoints)
fmt.Scanln(&docTopic)
// TODO: Buat satu tugas untuk setiap tipe (BugFix, Feature, Documentation)
// TODO: Kumpulkan semua tugas dalam satu slice []Task
// TODO: Panggil PrintBacklog dengan slice berisi tugas
}
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