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ềtruenế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ềfalsekhi 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 BoHã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.
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ềfalsemà 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ònhas(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ặpforduyệ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: UlyssesCode 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))
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
1Nền tảng về OOP
Tệp bên ngoàiGiới thiệu về OOPLớp và đối tượngTừ khóa selfPhương thứcThuộc tínhHàm khởi tạo (_init)Ôn tập: máy tính đơn giản4Tính đa hình
Xem lại cách ghi đè phương thứcĐịnh kiểu vịtLớp và phương thức trừu tượngThiết kế interfaceÔn tập: máy tính hình học7Tín hiệu
Tín hiệu là gì?Khai báo và phát tín hiệuKết nối với tín hiệuTín hiệu có đối sốÔn tập: hệ thống sức khỏe10Các mẫu thiết kế phần 2
Mẫu lệnhMẫu bộ chuyển đổiMẫu trang tríMẫu phương thức khuôn mẫuMẫu trạng tháiMẫu tổng hợp2Thuộc tính của lớp
Biến instance và biến staticHàm staticPhương thức thiết lập thuộc tínhPhương thức lấy thuộc tínhQuy ước về tính riêng tưÔn tập: trình quản lý tài khoản ngân hàng5Tính đóng gói
Thành viên công khai và riêng tưXác thực bằng phương thức setterẨn thông tinThuộc tính chỉ đọcÔn tập: hệ thống hồ sơ học sinh8Khái niệm OOP nâng cao
Kết hợp và kế thừaLớp bên trongNode dưới dạng thành phầnRefCounted và NodeEnum trong lớp3Kế thừa
Kế thừa cơ bảnTừ khóa superGhi đè phương thứcChuỗi kế thừaKiểm tra kiểu bằng isTổng kết: phân cấp nhân viên6Phương thức đặc biệt
Giới thiệu về phương thức ảoPhương thức _to_stringTrình lặp tùy chỉnhÔn tập: danh sách tùy chỉnhTự luyện tập: Trình biên dịch GDScript online