Menu
Coddy logo textTech

Information Hiding

Part of the Object Oriented Programming section of Coddy's Python journey — lesson 30 of 64.

Information hiding restricts direct access to object components, requiring all interactions to occur through well-defined interfaces. This protects internal data from unauthorized access.

Here is an example of a class with different levels of information hiding:

class BankAccount:
    def __init__(self, owner, initial_balance):
        self.owner = owner                    # Public - can be accessed directly
        self._balance = initial_balance       # Protected - internal use
        self.__account_number = "ACC123456"   # Private - hidden from outside

Add methods that provide controlled access to hidden data:

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):
        # Safe way to show partial private data
        return f"Owner: {self.owner}, Account: ***{self.__account_number[-4:]}"

Use the class through its public interface:

account = BankAccount("Alice", 1000)

Access public data directly:

print(account.owner)  # Alice - public access OK

Use controlled methods for protected data:

print(account.get_balance())  # 1000 - controlled access
account.deposit(500)
print(account.get_balance())  # 1500 - balance changed safely

Try to access hidden data:

print(account.get_account_info())  # Owner: Alice, Account: ***3456
# print(account.__account_number)  # AttributeError - hidden

The private attribute is name-mangled but still technically accessible:

# This works but violates information hiding:
print(account._BankAccount__account_number)  # ACC123456

Output:

Alice
1000
1500
Owner: Alice, Account: ***3456
ACC123456

Key Point: Information hiding protects internal data by making it private or protected, then providing controlled access through public methods. This prevents direct manipulation of sensitive data and ensures data integrity through validation in the access methods.

challenge icon

Challenge

Medium

In this challenge, you'll implement a secure messaging system with comprehensive testing to validate your solution.

You need to edit securemessenger.py to implement the SecureMessenger class following information hiding principles. The file contains detailed TODO comments to guide your implementation.

Key requirements include:

  • Proper encapsulation of credentials and messages
  • Authentication before allowing message operations
  • Security monitoring through login attempt tracking
  • Precise return messages as specified in the TODOs

Cheat sheet

Information hiding restricts direct access to object components through access modifiers:

  • public - accessible directly (no underscore)
  • _protected - internal use (single underscore)
  • __private - hidden from outside (double underscore)
class BankAccount:
    def __init__(self, owner, initial_balance):
        self.owner = owner                    # Public
        self._balance = initial_balance       # Protected
        self.__account_number = "ACC123456"   # Private

Provide controlled access through public methods:

def get_balance(self):
    return self._balance

def deposit(self, amount):
    if amount > 0:
        self._balance += amount
        return True
    return False

Private attributes are name-mangled but still accessible:

# Violates information hiding but works:
print(account._BankAccount__account_number)

Try it yourself

from securemessenger import SecureMessenger

# Test case handler
test_case = input()
if test_case == "default_test":
    # Standard test case from original problem
    messenger = SecureMessenger("user1")
    
    # Try to add messages before login
    print(messenger.add_message("Hello World!"))
    print(messenger.add_message("Secure Message"))
    
    # Attempt login with wrong password
    print(messenger.login("wrong_pass"))
    
    # Login with correct password
    print(messenger.login("secure123"))
    
    # Add messages after successful login
    print(messenger.add_message("Hello World!"))
    print(messenger.add_message("Secure Message"))
    
    # Retrieve messages
    print(messenger.get_messages())
    
    # Check login attempts
    print(messenger.get_login_attempts())
elif test_case == "custom_password":
    # Test with custom password
    messenger = SecureMessenger("admin", "admin123")
    print(messenger.login("wrong_password"))
    print(messenger.login("admin123"))
    print(messenger.get_login_attempts())
elif test_case == "multiple_login_attempts":
    # Test multiple login attempts
    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":
    # Test message management
    messenger = SecureMessenger("user3")
    print(messenger.login("secure123"))
    
    # Add multiple messages
    messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5"]
    for msg in messages:
        print(messenger.add_message(msg))
    
    # Verify all messages
    print(messenger.get_messages())
elif test_case == "empty_messages":
    # Test empty messages case
    messenger = SecureMessenger("user4")
    print(messenger.login("secure123"))
    print(messenger.get_messages())
elif test_case == "access_without_login":
    # Test access without login
    messenger = SecureMessenger("user5")
    print(messenger.add_message("Unauthorized message"))
    print(messenger.get_messages())
elif test_case == "attribute_privacy":
    # Test attribute privacy
    messenger = SecureMessenger("user6")
    
    # Public attribute
    print(f"Public username: {messenger.username}")
    
    # Private attributes - these should raise 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":
    # This test requires extending the class with a logout method
    # For testing purposes, we'll create a subclass with logout functionality
    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":
    # Stress test with many messages
    messenger = SecureMessenger("user8")
    print(messenger.login("secure123"))
    
    # Add 100 messages
    for i in range(1, 101):
        messenger.add_message(f"Message {i}")
    
    # Verify message count
    messages = messenger.get_messages()
    newline_char = '\n'  # Store the newline character in a variable
    message_count = len(messages.split(newline_char))
    print(f"Added 100 messages. Retrieved {message_count} messages.")
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming