Menu
Coddy logo textTech

Ocultação de Informação

Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 30 de 64.

A ocultação de informações restringe o acesso direto aos componentes do objeto, exigindo que todas as interações ocorram por meio de interfaces bem definidas. Isso protege os dados internos contra acesso não autorizado.

Aqui está um exemplo de uma classe com diferentes níveis de ocultação de informações:

class BankAccount:
    def __init__(self, owner, initial_balance):
        self.owner = owner                    # Público - pode ser acessado diretamente
        self._balance = initial_balance       # Protegido - uso interno
        self.__account_number = "ACC123456"   # Privado - oculto do exterior

Adicione métodos que forneçam acesso controlado a dados ocultos:

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):
        # Forma segura de mostrar dados privados parciais
        return f"Owner: {self.owner}, Account: ***{self.__account_number[-4:]}"

Use a classe por meio de sua interface pública:

account = BankAccount("Alice", 1000)

Acesse dados públicos diretamente:

print(account.owner)  # Alice - acesso público OK

Use métodos controlados para dados protegidos:

print(account.get_balance())  # 1000 - acesso controlado
account.deposit(500)
print(account.get_balance())  # 1500 - saldo alterado com segurança

Tente acessar dados ocultos:

print(account.get_account_info())  # Proprietário: Alice, Conta: ***3456
# print(account.__account_number)  # AttributeError - oculto

O atributo privado sofre name-mangling, mas ainda é tecnicamente acessível:

# Isso funciona, mas viola a ocultação de informações:
print(account._BankAccount__account_number)  # ACC123456

Saída:

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

Ponto Chave: A ocultação de informações protege os dados internos ao torná-los privados ou protegidos, fornecendo acesso controlado por meio de métodos públicos. Isso impede a manipulação direta de dados sensíveis e garante a integridade dos dados por meio de validação nos métodos de acesso.

challenge icon

Desafio

Médio

Neste desafio, você implementará um sistema de mensagens seguro com testes abrangentes para validar sua solução.

Você precisa editar o arquivo securemessenger.py para implementar a classe SecureMessenger seguindo os princípios de ocultação de informações (information hiding). O arquivo contém comentários TODO detalhados para guiar sua implementação.

Os requisitos principais incluem:

  • Encapsulamento adequado de credenciais e mensagens
  • Autenticação antes de permitir operações de mensagem
  • Monitoramento de segurança através do rastreamento de tentativas de login
  • Mensagens de retorno precisas conforme especificado nos TODOs

Folha de consulta

A ocultação de informações restringe o acesso direto aos componentes do objeto por meio de modificadores de acesso:

  • public - acessível diretamente (sem sublinhado)
  • _protected - uso interno (sublinhado simples)
  • __private - oculto do exterior (sublinhado duplo)
class BankAccount:
    def __init__(self, owner, initial_balance):
        self.owner = owner                    # Público
        self._balance = initial_balance       # Protegido
        self.__account_number = "ACC123456"   # Privado

Forneça acesso controlado por meio de métodos públicos:

def get_balance(self):
    return self._balance

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

Atributos privados sofrem "name mangling", mas ainda são acessíveis:

# Viola a ocultação de informações, mas funciona:
print(account._BankAccount__account_number)

Experimente você mesmo

from securemessenger import SecureMessenger

# Manipulador de casos de teste
test_case = input()
if test_case == "default_test":
    # Caso de teste padrão do problema original
    messenger = SecureMessenger("user1")
    
    # Tenta adicionar mensagens antes do login
    print(messenger.add_message("Hello World!"))
    print(messenger.add_message("Secure Message"))
    
    # Tentativa de login com senha incorreta
    print(messenger.login("wrong_pass"))
    
    # Login com a senha correta
    print(messenger.login("secure123"))
    
    # Adiciona mensagens após login bem-sucedido
    print(messenger.add_message("Hello World!"))
    print(messenger.add_message("Secure Message"))
    
    # Recupera mensagens
    print(messenger.get_messages())
    
    # Verifica tentativas de login
    print(messenger.get_login_attempts())
elif test_case == "custom_password":
    # Teste com senha personalizada
    messenger = SecureMessenger("admin", "admin123")
    print(messenger.login("wrong_password"))
    print(messenger.login("admin123"))
    print(messenger.get_login_attempts())
elif test_case == "multiple_login_attempts":
    # Teste de múltiplas tentativas de login
    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":
    # Teste de gerenciamento de mensagens
    messenger = SecureMessenger("user3")
    print(messenger.login("secure123"))
    
    # Adiciona múltiplas mensagens
    messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5"]
    for msg in messages:
        print(messenger.add_message(msg))
    
    # Verifica todas as mensagens
    print(messenger.get_messages())
elif test_case == "empty_messages":
    # Teste para o caso de mensagens vazias
    messenger = SecureMessenger("user4")
    print(messenger.login("secure123"))
    print(messenger.get_messages())
elif test_case == "access_without_login":
    # Teste de acesso sem login
    messenger = SecureMessenger("user5")
    print(messenger.add_message("Unauthorized message"))
    print(messenger.get_messages())
elif test_case == "attribute_privacy":
    # Teste de privacidade de atributos
    messenger = SecureMessenger("user6")
    
    # Atributo público
    print(f"Public username: {messenger.username}")
    
    # Atributos privados - estes devem gerar 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":
    # Este teste requer a extensão da classe com um método de logout
    # Para fins de teste, criaremos uma subclasse com funcionalidade de logout
    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":
    # Teste de estresse com muitas mensagens
    messenger = SecureMessenger("user8")
    print(messenger.login("secure123"))
    
    # Adiciona 100 mensagens
    for i in range(1, 101):
        messenger.add_message(f"Message {i}")
    
    # Verifica a contagem de mensagens
    messages = messenger.get_messages()
    newline_char = '\n'  # Armazena o caractere de nova linha em uma variável
    message_count = len(messages.split(newline_char))
    print(f"Added 100 messages. Retrieved {message_count} messages.")
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming