Diese Behauptung von Aleks Bromfield lautet:
Fast jede Sprache mit einem statischen Typsystem hat auch ein dynamisches Typsystem. Abgesehen von C fällt mir keine Ausnahme ein
Ist das eine berechtigte Behauptung? Ich verstehe, dass Java mit Reflection- oder Loading-Klassen zur Laufzeit ein bisschen wie folgt wird - aber kann diese Idee des "schrittweisen Tippens" auf eine große Anzahl von Sprachen ausgedehnt werden?
languages
dynamic-typing
static-typing
Falkenauge
quelle
quelle
Antworten:
Original Hochtöner hier. :)
Zunächst bin ich etwas amüsiert / schockiert, dass mein Tweet so ernst genommen wird! Wenn ich gewusst hätte, dass es so weit verbreitet wird, hätte ich mehr als 30 Sekunden damit verbracht, es zu schreiben!
Thiago Silva weist zutreffend darauf hin, dass "statisch" und "dynamisch" die Typprüfung genauer beschreiben als Schriftsysteme . Tatsächlich ist es nicht richtig zu sagen, dass eine Sprache entweder statisch oder dynamisch typisiert ist. Vielmehr hat eine Sprache ein Typensystem, und eine Implementierung dieser Sprache erzwingt das Typensystem möglicherweise durch statische Prüfung oder dynamische Prüfung oder beides oder beides (obwohl dies keine sehr ansprechende Sprachimplementierung wäre!).
Es gibt bestimmte Typsysteme (oder Merkmale von Typsystemen), die für statische Überprüfungen besser geeignet sind, und bestimmte Typsysteme (oder Merkmale von Typsystemen), die für dynamische Überprüfungen besser geeignet sind. Wenn Sie beispielsweise in Ihrer Sprache im Text eines Programms angeben können, dass ein bestimmter Wert immer ein Array von Ganzzahlen sein muss, ist es relativ einfach, ein statisches Prüfprogramm zu schreiben, um diese Eigenschaft zu überprüfen. Umgekehrt, wenn Ihre Sprache Untertypen hat und Downcasting zulässt, ist es relativ einfach, die Gültigkeit eines Downcasts zur Laufzeit zu überprüfen, dies ist jedoch zur Kompilierungszeit äußerst schwierig.
Was ich mit meinem Tweet wirklich gemeint habe, ist einfach, dass die überwiegende Mehrheit der Sprachimplementierungen eine gewisse dynamische Typprüfung durchführt. Ebenso hat die überwiegende Mehrheit der Sprachen einige Merkmale, die sich nur schwer (wenn nicht gar unmöglich) statisch überprüfen lassen. Downcasting ist ein Beispiel. Weitere Beispiele sind ein arithmetischer Überlauf, die Überprüfung der Array-Grenzen und die Überprüfung auf Null. Einige davon können unter bestimmten Umständen statisch überprüft werden, aber im Großen und Ganzen ist es schwierig, eine Sprachimplementierung zu finden, die zur Laufzeit keine Überprüfung durchführt.
Das ist keine schlechte Sache. Es ist nur eine Beobachtung, dass es viele interessante Eigenschaften gibt, die unsere Sprachen erzwingen sollen, und dass wir nicht wirklich wissen, wie man sie statisch überprüft. Und es ist eine Erinnerung daran, dass Unterscheidungen wie "statische Typen" gegenüber "dynamischen Typen" bei weitem nicht so eindeutig sind, wie manche Leute glauben machen. :)
Eine letzte Anmerkung: Die Begriffe "stark" und "schwach" werden in der Programmiersprachenforschung nicht wirklich verwendet und haben auch keine wirklich einheitliche Bedeutung. Im Allgemeinen habe ich festgestellt, dass jemand, der sagt, dass eine Sprache "stark tippt" und eine andere "schwach tippt", wirklich sagt, dass seine Lieblingssprache (die mit "stark tippt") dies verhindert einen Fehler machen, den die andere Sprache (die mit "schwacher Typisierung") nicht macht - oder umgekehrt, dass ihre Lieblingssprache (die mit "schwacher Typisierung") es ihnen erlaubt, eine coole Sache zu machen, die die andere Sprache (die "schwache Typisierung") macht eine mit "starker typisierung") tut das nicht.
quelle
Nun ja. Sie können Eigentumstaschen in jeder statisch typisierten Sprache haben. Die Syntax wird furchtbar sein, während Sie gleichzeitig alle Nachteile eines dynamisch typisierten Systems erfahren. Es gibt also keinen wirklichen Vorteil, es sei denn, der Compiler erlaubt Ihnen, eine schönere Syntax zu verwenden, wie es C #
dynamic
tut.Das geht auch in C ganz einfach.
Als Reaktion auf andere Antworten: Ich denke, die Leute verwechseln statisches / dynamisches Tippen mit starkem / schwachem Tippen. Bei der dynamischen Typisierung geht es darum, die Datenstruktur zur Laufzeit ändern zu können und Code Daten zu verwenden, die genau den Anforderungen des Codes entsprechen. Dies nennt man Duck Typing .
Das Erwähnen von Reflektion sagt nicht die ganze Geschichte aus, da Sie durch Reflektion die vorhandene Datenstruktur nicht ändern können. Sie können einer Klasse oder Struktur weder in C, C ++, Java noch in C # ein neues Feld hinzufügen. In dynamischen Sprachen ist das Hinzufügen neuer Felder oder Attribute zu vorhandenen Klassen nicht nur möglich, sondern durchaus üblich.
Betrachten Sie beispielsweise Cython , den Python-to-C-Compiler. Es wird statischer C-Code erstellt, das Typsystem behält jedoch seine dynamische Natur bei. C ist eine statisch typisierte Sprache, unterstützt jedoch dynamisches Schreiben in Python.
quelle
ExpandoObject
, obwohl dies im Gegensatz zu JavaScript oder Ruby ein Opt-In-Prozess ist. Trotzdem haben Sie einen sehr wichtigen Punkt angesprochen, nämlich, dass das Tippen von Enten (was 99% der Entwickler tatsächlich bedeuten, wenn sie "dynamisch getippt" sagen) und das Nachdenken überhaupt nicht dasselbe sind.True
um zu sagen, "dieses verrückte Objekt ist eine Instanz der Klasse, die ich definiere"). OCaml hat diese Funktion, soweit ich weiß, aber ich weiß es nicht wirklich.Dynamische Sprachen sind statische Sprachen . Was gemeinhin als "dynamisches Tippen" bezeichnet wird, ist ein Sonderfall des statischen Tippens - der Fall, in dem Sie sich darauf beschränkt haben, nur einen Typ zu haben. Stellen Sie sich als Gedankenexperiment vor, Sie schreiben ein Programm in Java oder C #, indem Sie nur
Object
Variablen / Felder / Parameter verwenden und unmittelbar vor dem Aufruf einer Methode ein Downcast durchführen. Es wäre genauer, Sprachen wie Python oder Javascript "unityped" zu nennen. (Diese Behauptung wird wahrscheinlich viele Leute verwirren / stören, wenn man bedenkt, dass ein solches Java- oder C # -Programm viele Untertypen verwenden würde, aber das liegt daran, dass die durchschnittliche OOP-Sprache Typen und Klassen zusammenführt. Weitere Informationen finden Sie im Blogbeitrag.)Beachten Sie, dass selbst C eine "dynamische" Typisierung hat - Sie können jeden Zeiger auf einen Zeiger
void
(und wenn der Speicher mir dientchar
) und wieder zurück setzen. Beachten Sie auch, dass dort keine Laufzeitüberprüfung stattfindet. Wenn Sie es falsch verstehen, genießen Sie Ihr undefiniertes Verhalten!quelle
String foo = (String) bar
es nicht heißt, dassbar
es sich tatsächlich um eine handeltString
. Das kann man nur zur Laufzeit genau wissen, daher sehe ich nicht, wie die Besetzung "statisch" erfolgt.dynamic
Objekt verwenden. Wenn Sie versuchen, einerobject
... eine Eigenschaft hinzuzufügen , können Sie das nicht.Der Unterschied zwischen statischer und dynamischer Typisierung besteht darin, dass der Typ eines Werts überprüft wird: Kompilierungszeit vs. Laufzeit. In Sprachen, in denen Werte ihren Typ haben (z. B. Java-Objekte), können Sie immer auf dynamisches Tippen zurückgreifen, auch wenn die Sprache statisches Tippen bevorzugt. Hier ist ein Beispiel in Java mit einer dynamisch typisierten Methode:
Beachten Sie, wie der Typ jedes Elements zur Laufzeit überprüft wird. Die äquivalente statisch typisierte Methode lautet:
In C behalten Werte (und insbesondere Zeiger) ihren Typ während der Laufzeit nicht bei - jeder Zeiger entspricht a
void *
. Stattdessen haben Variablen und Ausdrücke einen Typ. Um eine dynamische Typisierung zu erreichen, müssen Sie die Typinformationen selbst mitführen (z. B. als Feld in einer Struktur).quelle
frobnicate
Methode hier nicht aufrufen , ohne vorher darüber Bescheid zu wissenSpecificType
.dynamic
Schlüsselwort). Die Gleichsetzung von statischen zu Kompilierung- und dynamisch zur Laufzeit meist Muddies nur das Wasser.[1,2].Add([3,4])
ergeben[1,2,3,4]
,[1,2,[3,4]]
oder[4,6]
?Add
Methoden sollte fehlschlagen, da es keine Methode im Array gibt, die ein Array akzeptiert, da eine solche Methode mehrdeutig wäre. Duck Typing entschuldigt Sie nicht, verständliche Typen und Funktionen zu schreiben.Statische oder dynamische Typisierung bezieht sich im Wesentlichen darauf, wie Typen überprüft werden. Statische Typisierung bedeutet, dass die Überprüfung der Typen verschiedener Variablen oder Ausdrücke basierend auf dem tatsächlichen Code (normalerweise vom Compiler) überprüft wird, während in einem dynamischen Typensystem diese Überprüfung nur zur Laufzeit von der Laufzeitumgebung durchgeführt wird.
Ich glaube, der Text bezieht sich darauf, dass auch wenn die Typen tatsächlich statisch überprüft werden, sie auch zur Laufzeit, dh dynamisch, überprüft werden. Sie haben Java Reflection richtig erwähnt. Reflexion findet nur zur Laufzeit statt, und die Java Runtime Environment (JVM) führt bei Verwendung von Reflexion tatsächlich eine Typprüfung durch, was im Grunde genommen eine dynamische Typprüfung bedeutet.
quelle
Die Erklärung ist falsch: C hat auch ein wichtiges dynamisches Typensystem. Es überprüft es einfach nicht ("C ist stark typisiert, schwach überprüft"). Wenn Sie beispielsweise eine Struktur als
double
(reinternpret_cast
-Stil) behandeln, entsteht ein undefiniertes Verhalten - ein dynamischer Typfehler.quelle