Menu
CoddyTech

Pola Composite

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GDScript di Coddy. Pelajaran 55 dari 65.

Pola Composite membangun pohon yang membuat satu object dan sekelompok object memiliki method yang sama, sehingga kodemu dapat memperlakukan seluruh kelompok seperti satu item. Sebuah tas berisi item, sebuah tas dapat berisi tas lain, dan kamu dapat menanyakan beratnya dengan cara yang sama.

Kedua jenis memiliki parent abstrak yang sama:

# entry.gd
@abstract
class_name Entry
extends RefCounted

var entry_name: String

@abstract func get_weight() -> int
@abstract func display(indent: String) -> void

Daunnya adalah satu item:

# item.gd
class_name Item
extends Entry

var weight: int

func _init(n: String, w: int) -> void:
	entry_name = n
	weight = w

func get_weight() -> int:
	return weight

func display(indent: String) -> void:
	print(indent, entry_name, " (", weight, ")")

Komposit menampung entri lain dan menjawab dengan menanyai setiap entri tersebut. Sebuah tas memiliki bobot 1:

# bag.gd
class_name Bag
extends Entry

var contents: Array[Entry] = []

func _init(n: String) -> void:
	entry_name = n

func add(entry: Entry) -> void:
	contents.append(entry)

func get_weight() -> int:
	var total := 1
	for entry in contents:
		total += entry.get_weight()
	return total

func display(indent: String) -> void:
	print(indent, entry_name, " [", get_weight(), "]")
	for entry in contents:
		entry.display(indent + "  ")
# main.gd
var pouch := Bag.new("Pouch")
pouch.add(Item.new("Gem", 2))
var backpack := Bag.new("Backpack")
backpack.add(Item.new("Sword", 8))
backpack.add(pouch)
backpack.display("")
Backpack [12]
  Sword (8)
  Pouch [3]
    Gem (2)

Bag.get_weight() tidak pernah memeriksa apakah sebuah entri adalah item atau tas: fungsi ini memanggil method yang sama pada masing-masing, dan tas di dalamnya menjawab dengan menanyakan isinya sendiri. Rekursi itu menelusuri seluruh pohon, sedalam apa pun.

Tautan berjalan satu arah, dari tas ke isinya. Jika setiap entri juga menyimpan informasi tentang tas tempatnya berada, setiap tas dan entrinya akan saling menunjuk, membentuk siklus referensi yang tidak pernah dibebaskan. Saat entri perlu mengetahui lokasinya, teruskan informasi itu sebagai argumen, seperti display() meneruskan indentasi.

challenge icon

Tantangan

Sedang

Buat pohon folder dengan pola Composite. DiskEntry (disk_entry.gd) mendeklarasikan get_size(), count_files(), dan list_lines(indent). Tulis:

  • FileEntry: ukurannya adalah size miliknya sendiri, dihitung sebagai 1 file, dan list_lines() mencetak indentasi, lalu NAME (SIZE KB).
  • FolderEntry: add(entry) menyimpan child. Ukurannya adalah jumlah ukuran semua child-nya, jumlah file-nya adalah jumlah file semua child-nya, dan list_lines() mencetak indentasi, lalu NAME/ (SIZE KB), kemudian mencantumkan setiap child dengan indentasi ditambah dua spasi.

Kode yang disediakan membuat pohon dari input (jumlah baris berikutnya, lalu folder NAME, file NAME SIZE atau end, yang menutup folder saat ini), mencantumkannya, dan mencetak totalnya. Untuk folder Root yang berisi notes.txt (4 KB) dan folder Music dengan song.mp3 (300 KB), output-nya adalah:

Root/ (304 KB)
  notes.txt (4 KB)
  Music/ (300 KB)
    song.mp3 (300 KB)
Total: 304 KB, files: 2

Tulis kodemu di file_entry.gd dan folder_entry.gd. main.gd berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

extends Node

func _ready():
	# Kode input/output yang disediakan: biarkan apa adanya
	var open_folders: Array[FolderEntry] = []
	var root: FolderEntry = null
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		match parts[0]:
			"folder":
				var folder := FolderEntry.new(parts[1])
				if open_folders.is_empty():
					root = folder
				else:
					open_folders.back().add(folder)
				open_folders.append(folder)
			"file":
				open_folders.back().add(FileEntry.new(parts[1], int(parts[2])))
			"end":
				open_folders.pop_back()
	root.list_lines("")
	print("Total: %d KB, files: %d" % [root.get_size(), root.count_files()])
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 GDScript online