Menu
CoddyTech

Penyematan vs Agregasi

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 38 dari 107.

Kamu telah mempelajari bahwa embedding mempromosikan field dan method ke struct luar. Namun, Go juga mendukung agregasi, yaitu saat kamu menyertakan struct lain sebagai field bernama. Memahami kapan harus menggunakan masing-masing pendekatan adalah kunci untuk desain yang baik.

Dengan embedding, kamu menghilangkan nama field, dan anggota tipe di dalamnya dapat diakses secara langsung:

type Writer struct{}
func (w Writer) Write() string { return "writing" }

type Document struct {
    Writer  // embedding, tanpa nama field
}

d := Document{}
d.Write()  // akses langsung

Dengan agregasi, kamu memberi field nama eksplisit, sehingga nama itu diperlukan untuk mengakses tipe di dalamnya:

type Document struct {
    writer Writer  // agregasi, field bernama
}

d := Document{writer: Writer{}}
d.writer.Write()  // harus menggunakan nama field

Perbedaan utamanya terletak pada hubungan yang kamu nyatakan. Embedding menunjukkan hubungan "is-a", yaitu tipe luar mengambil identitas tipe dalam. Aggregation menunjukkan hubungan "has-a", yaitu tipe luar hanya berisi tipe dalam.

Gunakan embedding saat kamu ingin tipe luar memenuhi interface yang diimplementasikan oleh tipe dalam, atau saat akses langsung ke method membuat API lebih rapi. Gunakan aggregation saat tipe dalam merupakan detail implementasi yang tidak seharusnya diekspos, atau saat kamu ingin mengontrol secara eksplisit cara tipe dalam diakses.

challenge icon

Tantangan

Mudah

Mari buat sistem pembuatan laporan yang menunjukkan kapan sebaiknya menggunakan embedding dibandingkan aggregation. Kamu akan membuat sistem dengan beberapa komponen yang dapat diakses secara langsung (embedding), sementara komponen lainnya tetap menjadi detail implementasi internal (aggregation).

Kamu akan mengatur kodemu dalam tiga file:

  • formatter.go: Buat struct Formatter dengan field Style (string) dan method Format(text string) string yang mengembalikan teks yang dibungkus dengan style, seperti [Style] text [/Style]. Ini akan menjadi helper internal yang tidak boleh diekspos secara langsung.
  • report.go: Buat dua struct yang menangani pembuatan laporan dengan cara berbeda:
    • Struct Metadata dengan field Author dan Date. Ini merepresentasikan informasi publik yang seharusnya dapat diakses secara langsung.
    • Struct Report dengan field Title yang menyematkan Metadata (agar author dan date dapat diakses secara langsung), tetapi menggunakan aggregation untuk Formatter (sebagai detail implementasi internal dengan field bernama formatter).
    Tambahkan method Generate() string ke Report yang menggunakan formatter internal untuk memformat judul dan menyertakan metadata.
  • main.go: Baca detail laporan dari input, lalu buat Report dengan metadata yang disematkan dan formatter yang diagregasikan. Tunjukkan perbedaannya dengan mengakses author secara langsung pada report (melalui embedding), lalu membuat laporan berformat (yang menggunakan formatter tersembunyi secara internal).

Input berikut akan diberikan:

  • Baris 1: Judul laporan
  • Baris 2: Nama author
  • Baris 3: Tanggal
  • Baris 4: Style formatter

Method Format-mu harus mengembalikan:

[Style] text [/Style]

Method Generate-mu harus mengembalikan:

[formatted title]
Author: [Author], Date: [Date]

Dalam file main-mu, cetak tiga baris:

  1. Author yang diakses secara langsung pada Report (menunjukkan bahwa embedding membuat field dapat diakses secara langsung)
  2. Date yang diakses melalui nama tipe yang disematkan (report.Metadata.Date)
  3. Hasil pemanggilan Generate()

Contohnya, jika diberikan Quarterly Results, Jane Doe, 2024-01-15, dan BOLD, outputmu seharusnya:

Jane Doe
2024-01-15
[BOLD] Quarterly Results [/BOLD]
Author: Jane Doe, Date: 2024-01-15

Perhatikan bahwa Author dan Date dapat diakses secara langsung pada Report melalui embedding, sedangkan formatter tetap tersembunyi. Kamu tidak dapat memanggil report.Format() secara langsung karena formatter diagregasikan dengan field bernama. Ini menunjukkan penerapan hubungan "is-a" dibandingkan "has-a".

Coba sendiri

package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	scanner.Scan()
	title := scanner.Text()
	
	scanner.Scan()
	author := scanner.Text()
	
	scanner.Scan()
	date := scanner.Text()
	
	scanner.Scan()
	style := scanner.Text()
	
	// TODO: Buat struct Metadata yang berisi penulis dan tanggal
	
	// TODO: Buat Formatter dengan gaya yang diberikan
	
	// TODO: Buat Report yang menyematkan Metadata dan menggabungkan Formatter
	
	// TODO: Cetak penulis yang diakses langsung melalui Report (penyematan membuat field dapat diakses langsung)
	
	// TODO: Cetak tanggal yang diakses melalui nama tipe yang disematkan (report.Metadata.Date)
	
	// TODO: Cetak hasil pemanggilan Generate()
	
	// Hindari peringatan tentang variabel yang tidak digunakan (hapus baris-baris ini saat kamu menggunakan variabelnya)
	_ = title
	_ = author
	_ = date
	_ = style
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Go online