Tổng kết: Két an toàn
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 48 trên 70.
Thử thách
DễHãy xây dựng một lớp Vault sử dụng tính riêng tư dựa trên closure để tạo ra một hệ thống lưu trữ thực sự an toàn! Vault sẽ giữ nội dung bí mật, chỉ có thể truy cập khi cung cấp đúng mật khẩu.
Bạn sẽ tổ chức code trong hai tệp:
Vault.lua: Tạo một lớp, trong đó cả nội dung lẫn mật khẩu đều được lưu trong các biến cục bộ bên trong hàm khởi tạo, hoàn toàn ẩn khỏi các truy cập bên ngoài. Hàm khởi tạo:new(contents, password)sẽ lưu các giá trị này vào biến cục bộ, sau đó định nghĩa một phương thức trực tiếp trên instance của đối tượng::open(attemptedPassword): kiểm tra xem mật khẩu được nhập có khớp với mật khẩu đã lưu hay không. Nếu đúng, hàm trả về nội dung bí mật. Nếu sai, hàm trả về"Access Denied".
main.lua: Nạp module Vault và đọc ba đầu vào: nội dung bí mật cần lưu, mật khẩu cần đặt và mật khẩu được thử. Tạo một vault với nội dung và mật khẩu đó, sau đó thử mở vault bằng mật khẩu được nhập và in ra kết quả. Đồng thời, chứng minh rằng nội dung thực sự riêng tư bằng cách thử truy cập trực tiếp vàovault.contentsvà in ra giá trị nhận được.
Bạn sẽ nhận ba đầu vào:
- Nội dung bí mật cần lưu trong vault
- Mật khẩu dùng để bảo vệ vault
- Mật khẩu được thử để mở vault
Đầu ra gồm hai dòng:
Result: {resultFromOpen}
Direct access: {whatYouGetFromVaultContents}Ví dụ, nếu các đầu vào là Gold Coins, secret123 và secret123, đầu ra sẽ là:
Result: Gold Coins
Direct access: nilNếu các đầu vào là Diamond, mypass và wrongpass, đầu ra sẽ là:
Result: Access Denied
Direct access: nilĐiểm mấu chốt ở đây là cả contents lẫn password chỉ tồn tại dưới dạng biến cục bộ bên trong hàm khởi tạo. Phương thức :open() có thể truy cập chúng thông qua closure, nhưng không có gì khác có thể truy cập, kể cả vault.contents, vault._contents hay vault.password. Đây chính là tính đóng gói thực sự!
Tự làm thử
-- Nạp module Vault
local Vault = require('Vault')
-- Đọc các đầu vào
local contents = io.read()
local password = io.read()
local attemptedPassword = io.read()
-- TODO: Tạo két sắt với contents và password
-- TODO: Thử mở két sắt bằng mật khẩu đã nhập thử
-- TODO: In kết quả theo định dạng: "Result: {resultFromOpen}"
-- TODO: Thử truy cập trực tiếp vault.contents và in ra giá trị nhận được
-- In theo định dạng: "Direct access: {whatYouGetFromVaultContents}"
Tất cả bài học trong Lập trình hướng đối tượng
1Khái niệm “self”
Bảng với hàm“self” tường minhCú pháp dấu hai chấmDấu chấm và dấu hai chấmÔn tập: Điểm chuyển động4Dự án: Ngân hàng số
Thiết lập dự ánPhương thức nạp tiền2Mẫu Prototype cho lớp
Khái niệm PrototypeLiên kết bằng __indexHàm khởi tạo :new()Khởi tạo thuộc tínhCác instance độc lậpÔn tập: Nhà máy ô tô5Nạp chồng toán tử trong OOP
Cộng các đối tượngTrừ các đối tượngNối các đối tượngSo sánh các đối tượng (<, >)Ôn tập: phép tính với ví tiền8Đóng gói
Quy ước đặt tênClosure để bảo mậtTruy cập qua closureBảng chỉ đọcLogic kiểm tra hợp lệTổng kết: Két an toàn11Mẫu thiết kế (cơ bản)
Hàm tạo đối tượngBảng SingletonMẫu IteratorObserver (Listener)Ôn tập: Factory Logger3Trạng thái và hành vi của đối tượng
Biến instancePhương thức getterPhương thức setterThuộc tính tính toánĐịnh dạng chuỗiKiểm tra tính bằng nhauÔn tập: điểm số học sinh6Cơ bản về kế thừa
Thiết lập kế thừaKế thừa phương thứcMở rộng hàm khởi tạoThêm phương thức cho lớp conDùng chung và riêngÔn tập: hệ phân cấp hình dạngTự luyện tập: Trình biên dịch Lua online