Menu
CoddyTech

Ẩ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ài

Thê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 khai

Dù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àn

Thử 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ị ẩn

Thuộ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.

challenge icon

Thử thách

Trung bình

Trong 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.")
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 Python online