Menu
Coddy logo textTech

Information Hiding

Teil des Abschnitts Object Oriented Programming der Python-Journey von Coddy — Lektion 30 von 64.

Information Hiding beschränkt den direkten Zugriff auf Objektkomponenten und erfordert, dass alle Interaktionen über wohldefinierte Schnittstellen erfolgen. Dies schützt interne Daten vor unbefugtem Zugriff.

Hier ist ein Beispiel für eine Klasse mit verschiedenen Stufen der Informationskapselung:

class BankAccount:
    def __init__(self, owner, initial_balance):
        self.owner = owner                    # Öffentlich - kann direkt aufgerufen werden
        self._balance = initial_balance       # Geschützt - interne Verwendung
        self.__account_number = "ACC123456"   # Privat - von außen verborgen

Fügen Sie Methoden hinzu, die einen kontrollierten Zugriff auf verborgene Daten ermöglichen:

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):
        # Sicherer Weg, um teilweise private Daten anzuzeigen
        return f"Owner: {self.owner}, Account: ***{self.__account_number[-4:]}"

Verwenden Sie die Klasse über ihre öffentliche Schnittstelle:

account = BankAccount("Alice", 1000)

Greifen Sie direkt auf öffentliche Daten zu:

print(account.owner)  # Alice - öffentlicher Zugriff OK

Verwenden Sie kontrollierte Methoden für geschützte Daten:

print(account.get_balance())  # 1000 - kontrollierter Zugriff
account.deposit(500)
print(account.get_balance())  # 1500 - Kontostand sicher geändert

Versuchen Sie, auf versteckte Daten zuzugreifen:

print(account.get_account_info())  # Besitzer: Alice, Konto: ***3456
# print(account.__account_number)  # AttributeError - versteckt

Das private Attribut ist namensverfremdet (name-mangled), aber technisch gesehen immer noch zugänglich:

# Dies funktioniert, verletzt aber das Prinzip des Information Hiding:
print(account._BankAccount__account_number)  # ACC123456

Ausgabe:

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

Kernpunkt: Information Hiding schützt interne Daten, indem es sie als private oder protected kennzeichnet und dann einen kontrollierten Zugriff über public Methoden bereitstellt. Dies verhindert die direkte Manipulation sensibler Daten und gewährleistet die Datenintegrität durch Validierung in den Zugriffsmethoden.

challenge icon

Aufgabe

Mittel

In dieser Challenge implementierst du ein sicheres Nachrichtensystem mit umfassenden Tests, um deine Lösung zu validieren.

Du musst securemessenger.py bearbeiten, um die Klasse SecureMessenger nach den Prinzipien des Information Hiding zu implementieren. Die Datei enthält detaillierte TODO-Kommentare, die dich bei der Implementierung unterstützen.

Zu den wichtigsten Anforderungen gehören:

  • Korrekte Kapselung von Anmeldedaten und Nachrichten
  • Authentifizierung vor dem Zulassen von Nachrichtenoperationen
  • Sicherheitsüberwachung durch Verfolgung von Anmeldeversuchen
  • Präzise Rückgabemeldungen, wie in den TODOs angegeben

Spickzettel

Datenkapselung schränkt den direkten Zugriff auf Objektkomponenten durch Zugriffsmodifikatoren ein:

  • public - direkt zugänglich (kein Unterstrich)
  • _protected - interne Verwendung (einfacher Unterstrich)
  • __private - von außen verborgen (doppelter Unterstrich)
class BankAccount:
    def __init__(self, owner, initial_balance):
        self.owner = owner                    # Öffentlich
        self._balance = initial_balance       # Geschützt
        self.__account_number = "ACC123456"   # Privat

Ermöglichen Sie kontrollierten Zugriff über öffentliche Methoden:

def get_balance(self):
    return self._balance

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

Private Attribute unterliegen dem Name Mangling, sind aber weiterhin zugänglich:

# Verletzt die Datenkapselung, funktioniert aber:
print(account._BankAccount__account_number)

Probier es selbst

from securemessenger import SecureMessenger

# Testfall-Handler
test_case = input()
if test_case == "default_test":
    # Standard-Testfall aus der ursprünglichen Aufgabe
    messenger = SecureMessenger("user1")
    
    # Versuchen, Nachrichten vor dem Login hinzuzufügen
    print(messenger.add_message("Hello World!"))
    print(messenger.add_message("Secure Message"))
    
    # Login-Versuch mit falschem Passwort
    print(messenger.login("wrong_pass"))
    
    # Login mit korrektem Passwort
    print(messenger.login("secure123"))
    
    # Nachrichten nach erfolgreichem Login hinzufügen
    print(messenger.add_message("Hello World!"))
    print(messenger.add_message("Secure Message"))
    
    # Nachrichten abrufen
    print(messenger.get_messages())
    
    # Login-Versuche prüfen
    print(messenger.get_login_attempts())
elif test_case == "custom_password":
    # Test mit benutzerdefiniertem Passwort
    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 mehrere Login-Versuche
    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 Nachrichtenverwaltung
    messenger = SecureMessenger("user3")
    print(messenger.login("secure123"))
    
    # Mehrere Nachrichten hinzufügen
    messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5"]
    for msg in messages:
        print(messenger.add_message(msg))
    
    # Alle Nachrichten verifizieren
    print(messenger.get_messages())
elif test_case == "empty_messages":
    # Testfall für leere Nachrichten
    messenger = SecureMessenger("user4")
    print(messenger.login("secure123"))
    print(messenger.get_messages())
elif test_case == "access_without_login":
    # Teste Zugriff ohne Login
    messenger = SecureMessenger("user5")
    print(messenger.add_message("Unauthorized message"))
    print(messenger.get_messages())
elif test_case == "attribute_privacy":
    # Teste Attribut-Privatsphäre
    messenger = SecureMessenger("user6")
    
    # Öffentliches Attribut
    print(f"Public username: {messenger.username}")
    
    # Private Attribute - diese sollten einen AttributeError auslösen
    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":
    # Dieser Test erfordert die Erweiterung der Klasse um eine Logout-Methode
    # Zu Testzwecken erstellen wir eine Unterklasse mit Logout-Funktionalitä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":
    # Belastungstest mit vielen Nachrichten
    messenger = SecureMessenger("user8")
    print(messenger.login("secure123"))
    
    # 100 Nachrichten hinzufügen
    for i in range(1, 101):
        messenger.add_message(f"Message {i}")
    
    # Nachrichtenanzahl verifizieren
    messages = messenger.get_messages()
    newline_char = '\n'  # Speichere das Zeilenumbruchzeichen in einer Variablen
    message_count = len(messages.split(newline_char))
    print(f"Added 100 messages. Retrieved {message_count} messages.")
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Object Oriented Programming