Menu
CoddyTech

Trình lặp tùy chỉnh

Thuộc phần Lập trình hướng đối tượng trong hành trình GDScript của Coddy. Bài học 33 trên 65.

Python khiến một lớp hoạt động như một danh sách bằng các phương thức đặc biệt như __len__, __getitem__, __contains__ và __iter__. Godot chỉ có các phương thức ảo cho một trong những chức năng này, đó là vòng lặp for. Ba phương thức giúp for item in my_object: hoạt động:

  • _iter_init(iter) chạy một lần, trước vòng lặp đầu tiên. Phương thức này đặt vị trí bắt đầu và trả về true nếu có phần tử đầu tiên.
  • _iter_get(position) trả về phần tử ở vị trí hiện tại, và biến vòng lặp nhận giá trị đó.
  • _iter_next(iter) chạy trước mỗi vòng lặp tiếp theo. Phương thức này chuyển đến vị trí kế tiếp và trả về false khi không còn phần tử nào, khiến vòng lặp kết thúc.
# team.gd
class_name Team
extends RefCounted

var _members: Array[String] = []

func add(member: String) -> void:
	_members.append(member)

func _iter_init(iter: Array) -> bool:
	iter[0] = 0
	return iter[0] < _members.size()

func _iter_next(iter: Array) -> bool:
	iter[0] += 1
	return iter[0] < _members.size()

func _iter_get(position):
	return _members[position]

iter là một mảng có một ô mà Godot tạo ra cho mỗi vòng lặp. iter[0] lưu vị trí của vòng lặp đó, và Godot truyền giá trị này cho _iter_get(). Giờ đây, Team có thể hoạt động trong vòng lặp for:

var team := Team.new()
team.add("Ada")
team.add("Bo")
for member in team:
	print(member) # Ada, rồi đến Bo

Hãy giữ vị trí trong iter[0], không phải trong một biến thành viên như _position. Mỗi vòng lặp có iter riêng, nên hai vòng lặp trên cùng một đội, kể cả khi vòng này nằm bên trong vòng kia, sẽ không ảnh hưởng đến nhau. Nếu dùng biến thành viên, vòng lặp bên trong sẽ làm thay đổi vị trí của vòng lặp bên ngoài.

Các thao tác khác của danh sách không có phương thức ảo: len(team) và team[0] sẽ gây lỗi. Hãy viết các phương thức thông thường có tên giống như của Array, chẳng hạn size(), get_at(index) và has(member). Đừng kiểm tra phần tử có nằm trong danh sách hay không bằng in: "Ada" in team kiểm tra xem Team có thuộc tính hoặc phương thức tên là Ada hay không, vì vậy kết quả là false.

challenge icon

Thử thách

Dễ

Viết lớp Bookshelf trong tệp bookshelf.gd. Lớp này lưu các tựa sách trong _titles và chứa tối đa _capacity cuốn sách:

  • add(title) thêm tựa sách vào cuối danh sách và trả về true, hoặc trả về false mà không thêm sách nếu giá sách đã đầy hoặc đã có tựa sách đó.
  • size() trả về số sách, còn has(title) cho biết tựa sách có trên giá hay không.
  • get_at(index) trả về tựa sách ở chỉ số đó, hoặc chuỗi rỗng nếu chỉ số nằm ngoài phạm vi của giá sách.
  • _iter_init(), _iter_next() và _iter_get() cho phép vòng lặp for duyệt các tựa sách theo thứ tự chúng được thêm vào.

Code được cung cấp đọc sức chứa, số tựa sách và từng tựa sách trên một dòng, rồi báo những tựa sách không thể thêm vào. Code in ra số sách, liệt kê chúng bằng vòng lặp for trên giá sách, sau đó đọc thêm một tựa sách và in ra liệu giá sách có tựa đó hay không, cùng với cuốn sách cuối cùng. Với sức chứa 3, các tựa sách Dune, Emma, Dune, Ulysses, Hamlet và nội dung tìm kiếm Emma, chương trình in ra:

Could not add: Dune
Could not add: Hamlet
Books: 3
1. Dune
2. Emma
3. Ulysses
Has Emma: true
Last: Ulysses

Code của bạn nằm trong bookshelf.gd. main.gd chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

extends Node

func _ready():
	# Đoạn code đầu vào/đầu ra đã cho: giữ nguyên
	var shelf := Bookshelf.new(int(OS.read_string_from_stdin()))
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var title := OS.read_string_from_stdin()
		if not shelf.add(title):
			print("Could not add: " + title)
	print("Books: %d" % shelf.size())
	var number := 1
	for title in shelf:
		print("%d. %s" % [number, title])
		number += 1
	var query := OS.read_string_from_stdin()
	print("Has %s: %s" % [query, shelf.has(query)])
	print("Last: " + shelf.get_at(shelf.size() - 1))
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch GDScript online