Ẩn thông tin
Thuộc phần Lập trình hướng đối tượng trong hành trình Python của Coddy. Bài học 30 trên 64.
Việc ẩn thông tin hạn chế quyền truy cập trực tiếp vào các thành phần của đối tượng, yêu cầu mọi tương tác phải diễn ra thông qua các giao diện được xác định rõ. Điều này bảo vệ dữ liệu nội bộ khỏi truy cập trái phép.
Đây là ví dụ về một lớp có các mức độ ẩn thông tin khác nhau:
class BankAccount:
def __init__(self, owner, initial_balance):
self.owner = owner # Công khai: có thể truy cập trực tiếp
self._balance = initial_balance # Được bảo vệ: dùng trong nội bộ
self.__account_number = "ACC123456" # Riêng tư: không thể truy cập từ bên ngoàiThêm các phương thức để kiểm soát quyền truy cập vào dữ liệu ẩn:
class BankAccount:
def __init__(self, owner, initial_balance):
self.owner = owner
self._balance = initial_balance
self.__account_number = "ACC123456"
def deposit(self, amount):
if amount > 0:
self._balance += amount
return True
return False
def withdraw(self, amount):
if amount > 0 and amount <= self._balance:
self._balance -= amount
return True
return False
def get_balance(self):
return self._balance
def get_account_info(self):
# Cách hiển thị an toàn một phần dữ liệu riêng tư
return f"Owner: {self.owner}, Account: ***{self.__account_number[-4:]}"Sử dụng lớp thông qua giao diện công khai:
account = BankAccount("Alice", 1000)Truy cập trực tiếp vào dữ liệu công khai:
print(account.owner) # Alice: có thể truy cập công khaiDùng các phương thức có kiểm soát để truy cập dữ liệu được bảo vệ:
print(account.get_balance()) # 1000: truy cập có kiểm soát
account.deposit(500)
print(account.get_balance()) # 1500: số dư thay đổi an toànThử truy cập dữ liệu ẩn:
print(account.get_account_info()) # Chủ tài khoản: Alice, tài khoản: ***3456
# print(account.__account_number) # AttributeError: bị ẩnThuộc tính riêng được đổi tên nhưng về mặt kỹ thuật vẫn có thể truy cập:
# Cách này chạy được nhưng vi phạm nguyên tắc che giấu thông tin:
print(account._BankAccount__account_number) # ACC123456Đầu ra:
Alice
1000
1500
Owner: Alice, Account: ***3456
ACC123456Ý chính: Ẩn thông tin giúp bảo vệ dữ liệu nội bộ bằng cách đặt dữ liệu ở chế độ riêng tư hoặc được bảo vệ, sau đó cung cấp quyền truy cập có kiểm soát thông qua các phương thức công khai. Cách này ngăn việc thao tác trực tiếp với dữ liệu nhạy cảm và đảm bảo tính toàn vẹn của dữ liệu thông qua bước xác thực trong các phương thức truy cập.
Thử thách
Trung bìnhTrong thử thách này, bạn sẽ triển khai một hệ thống nhắn tin bảo mật và kiểm thử toàn diện để xác thực lời giải.
Bạn cần chỉnh sửa securemessenger.py để triển khai lớp SecureMessenger theo nguyên tắc che giấu thông tin. Tệp này có các chú thích TODO chi tiết hướng dẫn bạn triển khai.
Các yêu cầu chính gồm:
- Đóng gói thông tin đăng nhập và tin nhắn đúng cách
- Xác thực trước khi cho phép thao tác với tin nhắn
- Theo dõi bảo mật thông qua việc ghi nhận số lần đăng nhập
- Thông báo trả về chính xác như được nêu trong các TODO
Tự làm thử
from securemessenger import SecureMessenger
# Xử lý test case
test_case = input()
if test_case == "default_test":
# Test case tiêu chuẩn từ bài toán gốc
messenger = SecureMessenger("user1")
# Thử thêm tin nhắn trước khi đăng nhập
print(messenger.add_message("Hello World!"))
print(messenger.add_message("Secure Message"))
# Thử đăng nhập bằng mật khẩu sai
print(messenger.login("wrong_pass"))
# Đăng nhập bằng mật khẩu đúng
print(messenger.login("secure123"))
# Thêm tin nhắn sau khi đăng nhập thành công
print(messenger.add_message("Hello World!"))
print(messenger.add_message("Secure Message"))
# Lấy tin nhắn
print(messenger.get_messages())
# Kiểm tra số lần thử đăng nhập
print(messenger.get_login_attempts())
elif test_case == "custom_password":
# Kiểm tra với mật khẩu tùy chỉnh
messenger = SecureMessenger("admin", "admin123")
print(messenger.login("wrong_password"))
print(messenger.login("admin123"))
print(messenger.get_login_attempts())
elif test_case == "multiple_login_attempts":
# Kiểm tra nhiều lần thử đăng nhập
messenger = SecureMessenger("user2")
print(messenger.login("attempt1"))
print(messenger.login("attempt2"))
print(messenger.login("attempt3"))
print(messenger.login("secure123"))
print(messenger.get_login_attempts())
elif test_case == "message_management":
# Quản lý Test message
messenger = SecureMessenger("user3")
print(messenger.login("secure123"))
# Thêm nhiều tin nhắn
messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5"]
for msg in messages:
print(messenger.add_message(msg))
# Kiểm tra tất cả tin nhắn
print(messenger.get_messages())
elif test_case == "empty_messages":
# Kiểm tra trường hợp không có tin nhắn
messenger = SecureMessenger("user4")
print(messenger.login("secure123"))
print(messenger.get_messages())
elif test_case == "access_without_login":
# Kiểm tra quyền truy cập khi chưa đăng nhập
messenger = SecureMessenger("user5")
print(messenger.add_message("Unauthorized message"))
print(messenger.get_messages())
elif test_case == "attribute_privacy":
# Kiểm tra tính riêng tư của thuộc tính (attribute)
messenger = SecureMessenger("user6")
# Thuộc tính công khai
print(f"Public username: {messenger.username}")
# Các thuộc tính riêng tư: truy cập chúng sẽ gây ra AttributeError
try:
print(messenger.__password)
except AttributeError as e:
print("Password is private: AttributeError")
try:
print(messenger.__messages)
except AttributeError as e:
print("Messages are private: AttributeError")
try:
print(messenger.__login_attempts)
except AttributeError as e:
print("Login attempts are private: AttributeError")
try:
print(messenger.__is_logged_in)
except AttributeError as e:
print("Login status is private: AttributeError")
elif test_case == "login_logout_sequence":
# Test case này cần mở rộng lớp (class) bằng một phương thức (method) đăng xuất
# Để kiểm tra, ta sẽ tạo một lớp con có chức năng đăng xuất
class ExtendedMessenger(SecureMessenger):
def logout(self):
self._SecureMessenger__is_logged_in = False
return "Logged out successfully"
messenger = ExtendedMessenger("user7")
print(messenger.login("secure123"))
print(messenger.add_message("Test message"))
print(messenger.get_messages())
print(messenger.logout())
print(messenger.get_messages())
elif test_case == "stress_test":
# Kiểm tra khả năng chịu tải với nhiều tin nhắn
messenger = SecureMessenger("user8")
print(messenger.login("secure123"))
# Thêm 100 tin nhắn
for i in range(1, 101):
messenger.add_message(f"Message {i}")
# Kiểm tra số lượng tin nhắn
messages = messenger.get_messages()
newline_char = '\n' # Lưu ký tự xuống dòng vào một biến (variable)
message_count = len(messages.split(newline_char))
print(f"Added 100 messages. Retrieved {message_count} messages.")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ề lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTham số selfPhương thứcThuộc tínhPhương thức khởi tạo (__init__)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnHàm super()Ghi đè phương thứcKế thừa đa lớpThứ tự phân giải phương thứcÔn tập: hệ thống phân cấp nhân viên2Decorator
Giới thiệu về decoratorDecorator thuộc tínhDecorator phương thức tĩnhDecorator phương thức lớp5Tính đa hình
Xem lại cách ghi đè phương thứcKiểu gõ vịtLớp và phương thức trừu tượngThiết kế giao diệnÔn tập: máy tính hình học8Các khái niệm OOP nâng cao
Kết hợp và kế thừaMixinPhương thức tĩnh và phương thức lớpDecorator lớpTrình quản lý ngữ cảnhTự luyện tập: Trình biên dịch Python online