Menu
CoddyTech

Dùng chung và riêng

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

Khi làm việc với tính kế thừa, bạn cần hiểu mỗi phần dữ liệu nằm ở đâu. Một số thuộc tính được dùng chung: được định nghĩa trong lớp cha và có thể truy cập từ tất cả các lớp con. Những thuộc tính khác là riêng biệt: được tạo riêng trong lớp con hoặc đối tượng.

Hãy xem xét hệ thống phân cấp này:

local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia"  -- Dùng chung: định nghĩa trên lớp (class)

function Animal:new(name)
    local obj = {name = name}  -- Riêng biệt: lưu trên từng instance
    setmetatable(obj, Animal)
    return obj
end
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark"  -- Dùng chung cho mọi đối tượng Dog

function Dog:new(name, breed)
    local obj = Animal.new(Animal, name)
    obj.breed = breed  -- Riêng biệt: mỗi đối tượng Dog có breed riêng
    setmetatable(obj, Dog)
    return obj
end

Khi tạo một đối tượng Dog, một số giá trị tồn tại trực tiếp trên đối tượng, còn những giá trị khác được tìm thấy thông qua chuỗi tra cứu:

local rex = Dog:new("Rex", "German Shepherd")

-- Chỉ thuộc instance này (được lưu trên rex)
print(rex.name)    -- "Rex"
print(rex.breed)   -- "German Shepherd"
-- Dùng chung (tìm thấy qua tra cứu)
print(rex.sound)   -- "bark" (từ Dog)
print(rex.kingdom) -- "Animalia" (từ Animal)

Điểm khác biệt chính: các trường được gán cho obj trong hàm khởi tạo là riêng biệt với từng đối tượng, còn các trường được định nghĩa trực tiếp trên bảng lớp sẽ được chia sẻ giữa mọi đối tượng của lớp đó và các lớp con.

challenge icon

Thử thách

Dễ

Hãy khám phá cách dữ liệu đi qua hệ thống kế thừa bằng cách xây dựng hệ thống lớp Creature và Dragon. Bạn sẽ thấy rõ thuộc tính nào được chia sẻ giữa mọi instance và thuộc tính nào là riêng của từng đối tượng.

Bạn sẽ sắp xếp code trong ba tệp:

  • Creature.lua: Định nghĩa lớp cha với thuộc tính cấp lớp được chia sẻ world = "Fantasy Realm" mà mọi sinh vật đều dùng chung. Thêm hàm khởi tạo :new(name) để lưu tên sinh vật dưới dạng thuộc tính của instance.
  • Dragon.lua: Định nghĩa lớp con kế thừa từ Creature. Thêm thuộc tính cấp lớp được chia sẻ element = "fire" mà mọi rồng đều dùng chung. Hàm khởi tạo :new(name, color) cần gọi hàm khởi tạo của lớp cha để đặt tên, sau đó thêm color làm thuộc tính riêng của từng instance rồng.
  • main.lua: Tạo hai con rồng khác nhau và kiểm tra các thuộc tính của chúng để minh họa sự khác biệt giữa dữ liệu dùng chung và dữ liệu riêng.

Bạn sẽ nhận hai đầu vào:

  1. Tên và màu của con rồng thứ nhất, được phân tách bằng dấu phẩy (ví dụ: Smaug,red)
  2. Tên và màu của con rồng thứ hai, được phân tách bằng dấu phẩy (ví dụ: Draco,gold)

Trong tệp chính, hãy tạo cả hai con rồng với tên và màu tương ứng. Sau đó, in ra thông tin sau theo đúng thứ tự này:

  1. name của con rồng thứ nhất
  2. color của con rồng thứ nhất
  3. name của con rồng thứ hai
  4. color của con rồng thứ hai
  5. element của con rồng thứ nhất (được chia sẻ từ lớp Dragon)
  6. element của con rồng thứ hai (được chia sẻ từ lớp Dragon)
  7. world của con rồng thứ nhất (được chia sẻ từ lớp Creature)

Ví dụ, nếu đầu vào là Smaug,red và Draco,gold, đầu ra sẽ là:

Smaug
red
Draco
gold
fire
fire
Fantasy Realm

Hãy chú ý rằng name và color khác nhau ở mỗi con rồng (thuộc tính riêng của từng instance), còn element và world giống nhau ở cả hai (thuộc tính cấp lớp dùng chung, được tìm thấy thông qua chuỗi tra cứu).

Tự làm thử

-- main.lua: Tạo các con rồng và minh họa thuộc tính chung và thuộc tính riêng

local Dragon = require('Dragon')

-- Đọc đầu vào của con rồng thứ nhất (tên,màu sắc)
local input1 = io.read()
-- Đọc đầu vào của con rồng thứ hai (tên,màu sắc)
local input2 = io.read()

-- TODO: Phân tích đầu vào thứ nhất để lấy tên và màu sắc
-- Gợi ý: Dùng string.match với mẫu "([^,]+),([^,]+)"

-- TODO: Phân tích đầu vào thứ hai để lấy tên và màu sắc

-- TODO: Tạo con rồng thứ nhất với tên và màu sắc của nó

-- TODO: Tạo con rồng thứ hai với tên và màu sắc của nó

-- TODO: In lần lượt các mục sau:
-- 1. Tên của con rồng thứ nhất
-- 2. Màu sắc của con rồng thứ nhất
-- 3. Tên của con rồng thứ hai
-- 4. Màu của con rồng thứ hai
-- 5. Phần tử của con rồng thứ nhất (dùng chung từ lớp Dragon)
-- 6. Phần tử của con rồng thứ hai (dùng chung từ lớp Dragon)
-- 7. Thế giới của con rồng thứ nhất (dùng chung từ lớp Creature)
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 Lua online