Ich höre oft, dass neue Programmiersprachen dynamisch typisiert sind, aber was bedeutet es eigentlich, wenn wir sagen, eine Sprache sei dynamisch typisiert im Gegensatz zu statisch typisiert?
Antworten
Zu viele Anzeigen?Kompiliert vs. Interpretiert
"Wenn der Quellcode übersetzt wird"
- Quellcode : Originalcode (normalerweise von einem Menschen in einen Computer eingegeben)
- Übersetzung : Umwandlung von Quellcode in etwas, das ein Computer lesen kann (d.h. Maschinencode)
- Laufzeit : Zeitraum, in dem das Programm Befehle ausführt (nach der Kompilierung, falls kompiliert)
- Kompilierte Sprache : Vor der Laufzeit übersetzter Code
- Gedolmetschte Sprache : Code wird während der Ausführung übersetzt
Tippen
"Wenn Typen geprüft werden"
5 + '3'
ist ein Beispiel für einen Typfehler in stark typisiert Sprachen wie Go und Python, weil sie keinen "Typenzwang" zulassen -> die Möglichkeit, dass ein Wert in bestimmten Kontexten, z. B. beim Verschmelzen zweier Typen, seinen Typ ändert. Schwach typisiert Sprachen, wie z. B. JavaScript, keinen Typfehler auslösen (führt zu '53'
).
- Statisch : Typen werden vor der Ausführung geprüft
- Dynamisch : Typenprüfung während der Ausführung
Die Definitionen von "statisch & kompiliert" und "dynamisch & interpretiert" sind recht ähnlich... aber denken Sie daran, dass es heißt "wenn Typen geprüft werden" im Gegensatz zu "wenn der Quellcode übersetzt wird".
Sie erhalten dieselben Typfehler, unabhängig davon, ob die Sprache kompiliert oder interpretiert wird ! Sie müssen diese Begriffe begrifflich trennen.
Python-Beispiel
Dynamisch, interpretiert
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
silly(2)
Da Python sowohl interpretiert als auch dynamisch typisiert ist, übersetzt es nur den Code, den es ausführt, und führt eine Typüberprüfung durch. Die else
Block wird nie ausgeführt, also 5 + '3'
wird nicht einmal angeschaut!
Was wäre, wenn es statisch typisiert wäre?
Ein Typfehler würde ausgelöst werden, bevor der Code überhaupt ausgeführt wird. Der Code führt noch vor der Ausführung eine Typüberprüfung durch, auch wenn er interpretiert wird.
Und wenn es kompiliert wurde?
El else
Block würde vor der Ausführung übersetzt/geprüft werden, aber da er dynamisch typisiert ist, würde er keinen Fehler auslösen! Dynamisch typisierte Sprachen prüfen die Typen erst bei der Ausführung, und diese Zeile wird nie ausgeführt.
Beispiel gehen
Statisch, kompiliert
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
Die Typen werden vor der Ausführung geprüft (statisch) und der Typfehler wird sofort erkannt! Die Typen würden auch vor der Ausführung geprüft, wenn es sich um eine interpretierte Anwendung handeln würde, mit demselben Ergebnis. Bei einem dynamischen Programm würden keine Fehler auftreten, obwohl der Code während der Kompilierung geprüft wird.
Leistung
Eine kompilierte Sprache hat eine bessere Leistung zur Laufzeit, wenn sie statisch typisiert ist (im Gegensatz zu dynamisch); die Kenntnis der Typen ermöglicht eine Optimierung des Maschinencodes.
Statisch typisierte Sprachen sind zur Laufzeit leistungsfähiger, da sie während der Ausführung keine dynamische Typenprüfung durchführen müssen (sie werden vor der Ausführung geprüft).
Ebenso sind kompilierte Sprachen zur Laufzeit schneller, da der Code bereits übersetzt wurde und nicht erst "interpretiert"/übersetzt werden muss.
Beachten Sie, dass sowohl kompilierte als auch statisch typisierte Sprachen eine Verzögerung haben, bevor sie für die Übersetzung bzw. Typüberprüfung ausgeführt werden.
Mehr Unterschiede
Statische Typisierung fängt Fehler frühzeitig ab, anstatt sie während der Ausführung zu finden (besonders nützlich bei langen Programmen). Die statische Typisierung ist insofern "strenger", als sie nirgendwo in Ihrem Programm Typfehler zulässt und oft verhindert, dass Variablen ihren Typ ändern, was einen weiteren Schutz vor unbeabsichtigten Fehlern darstellt.
num = 2
num = '3' // ERROR
Die dynamische Typisierung ist flexibler, was einige zu schätzen wissen. In der Regel können Variablen ihren Typ ändern, was zu unerwarteten Fehlern führen kann.
Die Terminologie "dynamisch typisiert" ist leider irreführend. Alle Sprachen sind statisch typisiert, und Typen sind Eigenschaften von Ausdrücken (nicht von Werten, wie manche meinen). Es gibt jedoch Sprachen, die nur einen Typ haben. Diese werden uni-typisierte Sprachen genannt. Ein Beispiel für eine solche Sprache ist der untypisierte Lambda-Kalkül.
Im untypisierten Lambda-Kalkül sind alle Terme Lambda-Terme, und die einzige Operation, die auf einem Term ausgeführt werden kann, ist seine Anwendung auf einen anderen Term. Daher führen alle Operationen immer entweder zu einer unendlichen Rekursion oder zu einem Lambda-Term, signalisieren aber nie einen Fehler.
Würden wir jedoch das untypisierte Lambda-Kalkül mit primitiven Zahlen und arithmetischen Operationen erweitern, könnten wir unsinnige Operationen durchführen, z. B. zwei Lambda-Terme addieren: (x.x) + (y.y)
. Man könnte argumentieren, dass die einzige vernünftige Lösung darin besteht, in diesem Fall einen Fehler zu melden, aber dazu muss jeder Wert mit einem Indikator versehen werden, der angibt, ob der Term ein Lambda-Term oder eine Zahl ist. Der Additionsoperator prüft dann, ob tatsächlich beide Argumente als Zahlen gekennzeichnet sind, und meldet einen Fehler, wenn dies nicht der Fall ist. Beachten Sie, dass diese Markierungen no Typen, denn Typen sind Eigenschaften von Programmen, nicht von Werten, die von diesen Programmen erzeugt werden.
Eine uni-typisierte Sprache, die dies tut, wird dynamisch typisiert genannt.
Sprachen wie JavaScript, Python und Ruby sind alle uni-typisiert. Auch hier gilt, dass die typeof
Operator in JavaScript und der type
Funktion in Python haben irreführende Namen; sie geben die mit den Operanden verbundenen Tags zurück, nicht deren Typen. Ähnlich, dynamic_cast
in C++ und instanceof
in Java tun no Typenprüfungen durchführen.
Statisch typisierte Sprachen : Jede Variable und jeder Ausdruck ist bereits zur Kompilierzeit bekannt.
( int a;
a kann zur Laufzeit nur Werte vom Typ Ganzzahl annehmen)
Beispiele: C, C++, Java
Dynamisch typisierte Sprachen Variablen: Variablen können zur Laufzeit unterschiedliche Werte erhalten und ihr Typ wird zur Laufzeit definiert.
( var a;
a kann zur Laufzeit beliebige Werte annehmen)
Beispiele: Ruby, Python.
Statisch typisierte Sprachen führen zur Kompilierungszeit eine Typüberprüfung durch und der Typ kann sich NICHT ändern. (Machen Sie sich nicht über Kommentare zum Typ-Casting lustig, es wird eine neue Variable/Referenz erstellt).
Dynamisch typisierte Sprachen führen zur Laufzeit eine Typüberprüfung durch und der Typ einer Variablen KANN zur Laufzeit geändert werden.