Menu
CoddyTech

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.

challenge icon

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.

  • Weapon lưu weapon_name và damage, cả hai được đặt bởi hàm khởi tạo: Weapon.new("Sword", 7).
  • Knight lưu knight_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ành null.
  • 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ặc Ada has no weapon khi 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 weapon

Viế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())
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