Menu
CoddyTech

Thiết kế interface

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 24 trên 65.

Một giao diện là danh sách các phương thức mà một lớp cam kết sẽ có, nhưng không có mã triển khai chúng. Java và C# có từ khóa interface; GDScript thì không. Bạn có thể tạo thứ tương tự bằng một lớp trừu tượng có tất cả phương thức đều là phương thức trừu tượng:

# drawable.gd
@abstract
class_name Drawable
extends RefCounted

@abstract func draw() -> String
@abstract func resize(factor: int) -> void

Nó không có biến và phần thân phương thức. Nó mô tả những gì một thứ có thể vẽ có thể làm, còn mỗi lớp quyết định cách thực hiện:

# banner.gd
class_name Banner
extends Drawable

var text: String
var size := 1

func _init(t: String) -> void:
	text = t

func draw() -> String:
	return "Banner '%s' at size %d" % [text, size]

func resize(factor: int) -> void:
	size *= factor

Circle cũng có thể mở rộng Drawable, với radius cùng các phương thức draw() và resize() riêng. Code sử dụng giao diện chỉ phụ thuộc vào giao diện đó, nên hoạt động với mọi lớp mở rộng Drawable, kể cả những lớp được viết sau này:

func render_all(items: Array[Drawable]) -> void:
	for item in items:
		item.resize(2)
		print(item.draw())
var items: Array[Drawable] = [Banner.new("Sale"), Circle.new(3)]
render_all(items)
Banner 'Sale' at size 2
Circle with radius 6

Một lớp (class) chỉ có một lớp cha, nên nó chỉ có thể mở rộng một giao diện (interface). Khi một lớp đảm nhận vai trò thứ hai, chẳng hạn như được lưu vào tệp, hãy mở rộng giao diện chính và kiểm tra vai trò thứ hai bằng has_method():

if item.has_method("save"):
	item.save()

Giữ mỗi giao diện nhỏ gọn: chỉ gồm vài phương thức cùng phục vụ một vai trò. Lớp kế thừa giao diện đó chỉ cần viết những phương thức mình cần.

challenge icon

Thử thách

Dễ

Xây dựng một trình phát nội dung đa phương tiện xoay quanh một giao diện.

  • Trong playable.gd, biến Playable thành một giao diện: một lớp trừu tượng có các phương thức trừu tượng play() -> String và duration() -> int (tính bằng giây).
  • Song kế thừa Playable. play() trả về Playing song: TITLE by ARTIST, còn duration() trả về số giây của bài hát.
  • Video kế thừa Playable. play() trả về Playing video: TITLE in RESOLUTIONp (ví dụ: in 1080p), còn duration() trả về số giây của video.
  • Playlist chỉ biết Playable. play_all() in ra kết quả play() của từng mục, còn total_time() trả về tổng thời lượng theo định dạng M:SS (số giây gồm hai chữ số, ví dụ: 4:05).

Các hàm khởi tạo của Song và Video đã được viết sẵn. Code được cung cấp đọc số lượng mục tiếp theo, rồi đọc mỗi mục trên một dòng: song TITLE ARTIST SECONDS hoặc video TITLE RESOLUTION SECONDS. Code gọi play_all() và in ra tổng thời lượng. Với song Imagine Lennon 183 và video Trailer 1080 95, chương trình in ra:

Playing song: Imagine by Lennon
Playing video: Trailer in 1080p
Total time: 4:38

Code của bạn đặt trong playable.gd, song.gd, video.gd và playlist.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 có sẵn: giữ nguyên
	var count := int(OS.read_string_from_stdin())
	var playlist := Playlist.new()
	for i in count:
		var p := OS.read_string_from_stdin().split(" ")
		if p[0] == "song":
			playlist.add(Song.new(p[1], p[2], int(p[3])))
		else:
			playlist.add(Video.new(p[1], int(p[2]), int(p[3])))
	playlist.play_all()
	print("Total time: " + playlist.total_time())
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