Kết hợp và kế thừa
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 40 trên 65.
Các lớp tái sử dụng code theo hai cách. Kế thừa (extends) có nghĩa là một lớp là một loại của lớp khác: Mage là một Player. Kết hợp có nghĩa là một lớp có một thành phần: lớp đó lưu một đối tượng khác trong biến thành viên và giao việc cho đối tượng đó:
# motor.gd
class_name Motor
extends RefCounted
func start() -> String:
return "motor running"
# car.gd
class_name Car
extends RefCounted
var motor := Motor.new()
func start() -> String:
return "Car starts, " + motor.start()Car.new().start() trả về Car starts, motor running. Chiếc xe không biết động cơ hoạt động như thế nào: nó gọi motor.start(). Việc chuyển một lời gọi cho một bộ phận như thế này được gọi là ủy quyền. (Lớp này có tên là Motor vì Engine đã là một lớp của Godot.)
Kết hợp phát huy tác dụng khi các phần thay đổi hoặc kết hợp với nhau. Với tính kế thừa, nhân vật đi bộ và nhân vật bay là hai lớp con, còn một con dơi bắt đầu bay thì không thể đổi lớp. Với cách kết hợp, nhân vật có một bộ phận di chuyển, và chỉ cần gán một lần để thay đổi bộ phận đó:
# character.gd
class_name Character
extends RefCounted
var char_name: String
var movement: Movement
func _init(new_name: String, new_movement: Movement) -> void:
char_name = new_name
movement = new_movement
func move() -> String:
return char_name + " " + movement.move()
# main.gd
var bat := Character.new("Bat", Walk.new())
print(bat.move()) # Bat đi bộ
bat.movement = Fly.new()
print(bat.move()) # Bat bayỞ đây, Walk và Fly mở rộng một lớp Movement nhỏ: hai kỹ thuật này phối hợp với nhau. Một lớp GDScript chỉ có thể extend một lớp, vì vậy kết hợp thành phần cũng là cách để một đối tượng có nhiều khả năng bằng cách chứa nhiều phần.
Dùng kế thừa khi có quan hệ “là một” thực sự và không bao giờ thay đổi. Dùng kết hợp khi lớp “có” thứ gì đó, hoặc khi cần thay thế thành phần đó trong lúc trò chơi đang chạy.
Thử thách
DễMột hiệp sĩ không kế thừa từ vũ khí: hiệp sĩ có một vũ khí và có thể đổi vũ khí. Hãy tạo cả hai lớp.
Weaponlưuweapon_namevàdamage, cả hai được đặt bởi hàm khởi tạo:Weapon.new("Sword", 7).Knightlưuknight_name(từ hàm khởi tạo) và một vũ khí, ban đầu lànull.equip(new_weapon)thay thế vũ khí vàdrop()đặt lại vũ khí thànhnull.attack()trả vềAda attacks with Sword for 7 damage, dùng tên hiệp sĩ cùng tên và sát thương của vũ khí, hoặcAda has no weaponkhi không có vũ khí.
Code được cung cấp đọc tên hiệp sĩ và số lượng lệnh tiếp theo (equip Sword 7, drop, attack), rồi chạy chúng. Với Ada và attack, equip Sword 7, attack, equip Axe 12, attack, drop, attack, chương trình in ra:
Ada has no weapon
Equipped Sword
Ada attacks with Sword for 7 damage
Equipped Axe
Ada attacks with Axe for 12 damage
Dropped the weapon
Ada has no weaponViết code của bạn trong weapon.gd và knight.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 knight := Knight.new(OS.read_string_from_stdin())
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
if parts[0] == "equip":
knight.equip(Weapon.new(parts[1], int(parts[2])))
print("Equipped ", parts[1])
elif parts[0] == "drop":
knight.drop()
print("Dropped the weapon")
else:
print(knight.attack())
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ớpTự luyện tập: Trình biên dịch GDScript online