In einem dynamisch typisierten System haben Werte zur Laufzeit Typen, Variablen und Funktionen jedoch nicht. In einem statisch typisierten System sind die Typen von Variablen und Funktionen bekannt und werden beim Kompilieren überprüft. ZB in Python x
kann alles sein ; Wenn es zur Laufzeit 1
eine Zahl ist "foo"
, ist es eine Zeichenfolge. Sie wissen nur, welcher Typ x
zur Laufzeit vorhanden ist, und er kann bei jedem Ausführen des Programms anders sein. In einer Sprache wie Java würden Sie schreiben, int x
wenn x
es sich um eine Zahl handeln würde, und Sie würden beim Kompilieren wissen, dass es sich x
immer um eine Zahl handeln muss int
.
"Explizite" und "implizite" Typen beziehen sich beide auf statische Typsysteme. Das bestimmende Merkmal eines statischen System ist , dass die Typen sind bekannt bei der Kompilierung, aber nicht unbedingt , dass sie aus geschrieben werden müssen. In Java sind Typen explizit - Sie müssen sie ausschreiben. In Java könnte eine Methode folgendermaßen aussehen:
public int foo(String bar, Object baz) { ... }
Die Typen sind sowohl zur Kompilierungszeit bekannt (statisch) als auch ausgeschrieben (explizit). Es gibt jedoch auch Sprachen, die Sie nicht zwingen, den Typ auszuschreiben. Sie können den Typ einer Funktion aus ihrem Körper und ihrer Verwendung ableiten . Ein Beispiel wäre OCaml, wo Sie so etwas schreiben können:
let foo x = x + 1
Da Sie verwendet haben +
, kann OCaml herausfinden, dass x
dies int
alles für sich sein muss. Der Typ von foo
( foo : int -> int
) ist also zur Kompilierungszeit bekannt, genau wie im Java-Beispiel. Es ist völlig statisch. Da der Compiler jedoch selbst herausfinden kann, was die Typen sein müssen, müssen Sie sie nicht selbst aufschreiben: Sie sind implizit.
Kurz: Ob ein Typsystem explizit oder implizit ist, ist eine Eigenschaft statischer Systeme. Es ist eine ganz andere Frage, ob ein Typensystem dynamisch oder statisch ist.
Oft haben Sie Typsysteme, die manchmal explizit und manchmal implizit sind.
Ich glaube beispielsweise, dass Sie mit C # mithilfe des var
Schlüsselworts auf Typen schließen können . Anstatt also zu schreiben int x = 10
, können Sie schreiben, var x = 10
und der Compiler stellt fest, dass x
dies eine sein muss int
. C ++ macht etwas Ähnliches mit auto
. Diese Systeme sind in der Regel explizit, lassen jedoch Rückschlüsse zu.
Auf der anderen Seite gibt es Systeme, die normalerweise implizit sind, Sie jedoch manchmal zum Schreiben einer Typensignatur zwingen. Haskell ist ein gutes Beispiel. Meistens kann Haskell die Typen für Sie ableiten. Manchmal können Sie jedoch mehrdeutigen Code schreiben show . read
, bei dem Haskell die Typen nicht selbst herausfinden kann. In diesem Fall müssten Sie entweder show
oder explizit angeben read
. Darüber hinaus machen einige fortgeschrittenere Merkmale des Typsystems (wie der Rang-n-Polymorphismus) die Inferenz unentscheidbar - das heißt, es ist nicht garantiert, dass sie anhält. Dies bedeutet, dass Code, der diese Funktion verwendet, häufig explizite Typensignaturen benötigt.
statisch vs dynamisch beschreibt, wann Typen überprüft werden (mehr oder weniger zur Kompilierungszeit oder zur Ausführungszeit)
nominal vs strukturell beschreibt, wenn zwei Typen als gleich angesehen werden.
(Und es gibt Variationen, die bekannteste ist die Variante der strukturellen Typisierung, die nur berücksichtigt, was anstelle der gesamten als Ententypisierung bekannten Typisierung verwendet wird.)
Die vier Kombinationen (statisch nominal, statisch strukturell, dynamisch nominal, dynamisch strukturell) sind möglich, und Sprachen gehören oft nicht nur zu einer Klasse, sondern zu anderen.
Beispielsweise sind die Typsysteme von C ++ statisch, meist nominell, aber strukturell, wenn Sie Vorlagen berücksichtigen (und Sie können einen Teil der Probleme im Zusammenhang mit Konzepten in C ++ als Konflikt zwischen denjenigen betrachten, die vom Duck-Typing zu einer vollständigen Form des strukturellen Typings übergehen möchten diejenigen, die zur nominalen Eingabe gehen wollen). Die Verwendung von Klassen und Vererbung ermöglicht in einigen Fällen die Verwendung einer dynamischen und nominalen Typisierung.
Sprache, die in dynamischen Typsystemen häufig strukturelle Typisierung verwendet, aber CLOS als nominelle Aspekte.
quelle
Dies ist normalerweise nicht der Fall. Strukturelles Typisieren bedeutet, dass
B
es sich um einen Subtyp handelt, der der Schnittstelle von "A
BefriedigenA
" entspricht. Dies bedeutet normalerweise, Mitglieder mit demselben Namen zu haben. nicht nur die gleiche Struktur im Speicher.Dies unterscheidet sich von der nominativen Typisierung, bei der bei der Deklaration Supertypen angegeben werden müssen.
quelle
Die beste Erklärung, die ich für die Unterscheidung zwischen (tatsächlich unterstellten) dynamischen und statischen Typsystemen gesehen habe, ist in diesem Blog-Beitrag von Bob Harper:
Sein Hauptpunkt kann wie folgt zusammengefasst werden:
quelle