Was ist in der Programmiersprachenperspektive mit Subtypisierung gemeint? Ich habe gehört, dass "Vererbung keine Untertypisierung" ist. Was sind dann die Unterschiede zwischen Vererbung und Subtypisierung?
Was ist in der Programmiersprachenperspektive mit Subtypisierung gemeint? Ich habe gehört, dass "Vererbung keine Untertypisierung" ist. Was sind dann die Unterschiede zwischen Vererbung und Subtypisierung?
Antworten:
[Ich habe mich nicht eingehend mit den Problemen objektorientierter Typensysteme befasst, aber ich werde sagen, was ich weiß, um die Diskussion in Gang zu bringen.]
Die strukturelle Untertypisierung stellt keine verhaltensbezogene Untertypisierung sicher, da die Struktur eines Typs möglicherweise aus versehentlichen Gründen übereinstimmt. Die Definition des erwarteten Verhaltens ist jedoch nicht einfach. Daher verwenden viele Programmiersprachen einen Zwischenpunkt, an dem der Benutzer deklarieren muss, welcher Typ ein Subtyp von welchem ist. Dies wird als "nominelle Untertypisierung" bezeichnet . Siehe die Frage zu impliziter vs expliziter Untertypisierungfür eine Diskussion zu diesem Thema. Die Idee ist, dass der Programmierer die Verhaltensuntertypen für alle deklarierten Untertypen mit seinem eigenen Einfallsreichtum sicherstellen muss. Die Sprache kann keine Hilfe anbieten. Alle deklarierten Subtypen müssen jedoch mindestens strukturelle Subtypen sein. Andernfalls kann das Programm check nicht eingeben. Die Sprache kann dabei helfen. (Einige Programmiersprachen verfügen nicht über genügend Typsysteme, um dies zur Kompilierungszeit sicherzustellen. In diesem Fall würde der Typfehler zur Laufzeit erkannt, oder es könnten falsche Ergebnisse erzeugt werden. Solche Typlöcher sind offensichtlich unerwünscht.)
Wenn man in objektorientierten Programmen Unterklassen definiert, fügt man normalerweise öffentlich sichtbare Felder (oder Methoden) hinzu. In den meisten Programmiersprachen werden solche Unterklassen als nominelle Untertypen betrachtet. Die Frage ist, ob es sich auch um strukturelle Untertypen handelt. Wenn dies nicht der Fall ist, dh die Programmiersprache erlaubt es, nominelle Subtypen zu deklarieren, die keine strukturellen Subtypen sind, dann gibt es in der Programmiersprache Typlöcher.
In einfachen Fällen funktioniert das Hinzufügen von Feldern problemlos. Der Typ der Oberklasse erwartet weniger Felder als der Typ der Unterklasse. Wenn Sie also eine Instanz einer Unterklasse einfügen, in der eine Instanz der sueprclass erwartet wird, ignoriert das Programm nur die bereitgestellten zusätzlichen Felder, und es tritt kein Fehler auf.
Wenn jedoch die Ober- oder Unterklasse über Methoden verfügt, die Argumente desselben Typs annehmen oder Ergebnisse desselben Typs zurückgeben, treten Probleme auf. Dann ist der Schnittstellentyp der Unterklasse kein struktureller Untertyp des der Oberklasse. Weit verbreitete typsichere Programmiersprachen wie Java lassen solche Unterklassen nicht zu. Sie schränken die Sprache ein, um die Typensicherheit zu gewährleisten. Die Programmiersprache Eiffel soll die Typensicherheit geopfert haben, um stattdessen Flexibilität zu erhalten . Wenn man ein starkes Typensystem entwirft, das Flexibilität bewahrt, muss man das Prinzip aufgeben, dass Subklassen Subtypen hervorrufen. Daher der Titel der Arbeit "Inheritance is not subtyping". Die Autoren schlagen einen anderen Begriff der Subtypisierung höherer Ordnung vor, der stattdessen funktioniert. Kim Bruce hat auch einen eng verwandten Vorschlag namens "Matching", der den gleichen Effekt erzielt. Siehe diese Präsentation . Hilfreich ist auch ein Positionspapier von Andrew Black.
Die Semantik-Community ist wahrscheinlich schuld daran, das Problem weitgehend zu ignorieren. Wir haben es traditionell als ein praktisches Problem der Systemtechnik angesehen, das theoretisch von geringem Interesse ist. Wenn dies nicht der Fall ist und es tatsächlich einige semantische Arbeiten in diesem Bereich gibt, hoffe ich, dass die anderen Leute sie erwähnen werden.