Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| de:modul:m320_2024:learningunits:lu11:interface [2026/08/30 14:05] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | de:modul:m320_2024:learningunits:lu11:interface [2026/08/30 14:06] (aktuell) – ↷ Links angepasst, weil Seiten im Wiki verschoben wurden msuter | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| + | ====== LU11c - Interface in Python ====== | ||
| + | Schnittstellen spielen im Software Engineering eine wichtige Rolle. | ||
| + | Wenn eine Anwendung wächst, werden Aktualisierungen und Änderungen an der Codebasis immer schwieriger zu verwalten. | ||
| + | Hier erfahren Sie, wie Sie eine // | ||
| + | Grundsätzlich kann eine Schnittstelle als **Vertrag** verstanden werden. | ||
| + | Sie definiert eine gewisse Funktionalität durch Methoden. | ||
| + | Im Interface wird die Deklaration ohne Implementation festgehalten. (Anmerkung: man spricht oft auch von vollabstrakten Klassen, so z.B. bei C++) | ||
| + | |||
| + | Diese Funktionalität wird für die korrekte Funktion der Anwendung vorausgesetzt. Die implementierende Klasse nutzt die Deklaration der Schnittstelle, | ||
| + | |||
| + | ==== Beispiel: Objekte mit gleichartiger Funktionalität | ||
| + | Verschieden Objekte, die keine Beziehung zueinander aufweisen müssen, haben eine ähnliche Funktionalität, | ||
| + | |||
| + | {{modul: | ||
| + | //Abb: Klassen mit sinngleicher Funktionalität// | ||
| + | |||
| + | Obwohl die drei Klassen Mensch, Wasserflugzeug und Baum keine gemeinsame Basis (Oberklasse) haben, weisen alle die Fähigkeit '' | ||
| + | |||
| + | {{modul: | ||
| + | |||
| + | //Abb: Schnittstellen in UML// | ||
| + | |||
| + | Beachten Sie hier die Darstellung einer Schnittstellen-Beziehung als gestrichelte Linie (im Gegensatz zur Vererbung mit durchgezogener Linie). | ||
| + | |||
| + | {{modul: | ||
| + | |||
| + | //Abb: UML-Symbole Vererbung und Schnittstelle// | ||
| + | |||
| + | |||
| + | Das Beispiel verdeutlicht, | ||
| + | Im Code können entsprechende Objekte diese Funktionalität nutzen. | ||
| + | <code python> | ||
| + | a_human_object = Human(" | ||
| + | a_human_object.swim() | ||
| + | ··· | ||
| + | a_plane_object = Seaplane(" | ||
| + | a_plane_object.swim() | ||
| + | ··· | ||
| + | a_tree_object = Tree(" | ||
| + | a_tree_object.swim() | ||
| + | </ | ||
| + | Werden diese verschiedenen Objekte in einer Liste eingetragen, | ||
| + | |||
| + | Dieses Verhalten entspricht der Idee der Polymorphie. In Pyton wird das konkret mittels Duck-Typing umgesetzt. | ||
| + | |||
| + | ===== Das Duck-Typing ===== | ||
| + | <WRAP center round tip 60%> | ||
| + | Der Name // | ||
| + | <color # | ||
| + | </ | ||
| + | |||
| + | Python kennt das Konstrukt des Interface nicht. | ||
| + | Es wird ersetzt durch die Technik des // | ||
| + | Es stellt eine Typisierung dar, welche in dynamischen Sprachen verwendet wird. | ||
| + | Nebst Python auch bei Perl, Ruby, PHP, Javascript usw., wo der Typ oder die Klasse eines Objekts weniger wichtig ist als die Methode, die es definiert. | ||
| + | Mit Duck-Typing überprüfen wir Typen überhaupt nicht. Stattdessen prüfen wir, ob eine bestimmte Methode oder ein bestimmtes Attribut vorhanden ist. | ||
| + | |||
| + | ==== Wozu Duck-Typing verwenden? ==== | ||
| + | Dank // | ||
| + | Der Vorteil ist, dass dazu keine formale Schnittstelle vorhanden sein muss. | ||
| + | Gleichzeitig ist dies aber auch ein Nachteil, so dass entsprechende Checks eingebaut werden sollten, um Fehler zu vermeiden. | ||
| + | |||
| + | Das // | ||
| + | |||
| + | ==== Wie wird Duck-Typing verwendet? | ||
| + | Beim Duck-Typing werden beliebige Objekte in einer Liste gesammelt. | ||
| + | Wird die Liste traversiert (mit einer for-Schleife), | ||
| + | |||
| + | |||
| + | ==== Beispiel: Umsetzung einer pseudo Schnittstelle mit Duck-Typing ==== | ||
| + | |||
| + | <file python> | ||
| + | class People: | ||
| + | def swim(self): | ||
| + | print(' | ||
| + | |||
| + | class Tree: | ||
| + | def swim(self): | ||
| + | print(' | ||
| + | |||
| + | class Aeroplane: | ||
| + | def swim(self): | ||
| + | print(' | ||
| + | |||
| + | class Machine: | ||
| + | pass # kann nicht schwimmen | ||
| + | |||
| + | |||
| + | if __name__ == ' | ||
| + | print(' | ||
| + | |||
| + | container = [] | ||
| + | container.append(People()) | ||
| + | container.append(Tree()) | ||
| + | container.append(Aeroplane()) | ||
| + | container.append(Machine()) | ||
| + | |||
| + | for obj in container: | ||
| + | if hasattr(obj, | ||
| + | obj.swim() | ||
| + | </ | ||
| + | |||
| + | Das Programm liefert folgende Ausgabe: | ||
| + | |||
| + | < | ||
| + | schwimmen wie ein Mensch | ||
| + | schwimmen wie ein Baumstamm | ||
| + | schwimmen wie ein Wasserflugzeug | ||
| + | </ | ||
| + | ---- | ||
| + | |||
| + | Der Grund dafür liegt darin, dass Python als dynamische Sprache bei Methoden mit derselben Signatur so tut, also ob dafür eine Schnittstelle vorhanden wäre. | ||
| + | Das passiert automatisch und implizit (=versteckt). | ||
| + | Wie bereits erwähnt, wird daher in diesem Zusammenhang von einer // | ||
| + | |||
| + | === Beispiel: Informelle Schnittstelle === | ||
| + | |||
| + | {{modul: | ||
| + | |||
| + | //Abb: Die Schnittstelle '' | ||
| + | |||
| + | ---- | ||
| + | [[https:// | ||
| + | \\ | ||
| + | **Quellen**: | ||