Typ-System

Ein Typ-System vereinigt einen Typ mit jedem geschätzten Wert. Durch das Überprüfen des Flusses dieser Werte versucht ein Typ-System, zu sichern oder zu beweisen, dass keine Typ-Fehler vorkommen können. Das besondere fragliche Typ-System bestimmt genau, was einen Typ-Fehler einsetzt, aber im Allgemeinen ist das Ziel, Operationen zu verhindern, die eine bestimmte Art des Werts erwarten, der mit Werten wird verwendet, für die diese Operation Sinn (Logikfehler) nicht hat; Speicherfehler werden auch verhindert. Typ-Systeme werden häufig als ein Teil von Programmiersprachen angegeben, und in die Dolmetscher und Bearbeiter für sie eingebaut; obwohl sie auch als fakultative Werkzeuge durchgeführt werden können.

In der Informatik kann ein Typ-System als "ein lenksames syntaktisches Fachwerk definiert werden, um Ausdrücke gemäß den Arten von Werten zu klassifizieren, die sie schätzen".

Ein Bearbeiter kann auch den statischen Typ eines Werts verwenden, um die Lagerung zu optimieren, die es braucht und die Wahl von Algorithmen für Operationen auf dem Wert. In vielen C Bearbeitern wird der Datentyp zum Beispiel in 32 Bit gemäß der IEEE Spezifizierung für die einfache Präzision vertreten, die Punkt-Zahlen schwimmen lässt. Sie werden so Schwimmpunkt spezifische Mikroprozessor-Operationen auf jenen Werten (Schwimmpunkt-Hinzufügung, Multiplikation, usw.) verwenden.

Die Tiefe von Typ-Einschränkungen und die Weise ihrer Einschätzung betreffen das Schreiben der Sprache. Eine Programmiersprache kann weiter eine Operation mit unterschiedlichen konkreten Algorithmen auf jedem Typ im Fall vom Typ polymorphism vereinigen. Typ-Theorie ist die Studie von Typ-Systemen, obwohl die konkreten Typ-Systeme von Programmiersprachen aus praktischen Problemen der Computerarchitektur, der Bearbeiter-Durchführung und des Sprachdesigns entstehen.

Grundlagen

Das Zuweisen von Datentypen (das Schreiben) gibt Bedeutung Folgen von Bit. Typen haben gewöhnlich Vereinigungen entweder mit Werten im Gedächtnis oder mit Gegenständen wie Variablen. Weil jeder Wert einfach aus einer Folge von Bit in einem Computer besteht, macht Hardware keine innere Unterscheidung sogar zwischen Speicheradressen, Instruktionscode, Charakteren, ganzen Zahlen und Schwimmpunkt-Zahlen, unfähig seiend, zwischen ihnen gestützt auf dem Bit-Muster allein zu unterscheiden. Das Verbinden einer Folge von Bit und einem Typ informiert Programme und Programmierer, wie diese Folge von Bit verstanden werden sollte.

Durch Typ-Systeme zur Verfügung gestellte Vorteile schließen ein:

  • Abstraktion (oder Modularität) - Typen erlaubt Programmierern, an Programme an einem höheren Niveau zu denken als das Bit oder Byte, sich mit der auf niedriger Stufe Durchführung nicht sorgend. Zum Beispiel können Programmierer an eine Schnur als eine Sammlung von Charakter-Werten statt als eine bloße Reihe von Bytes denken. Oder Typen können Programmierern erlauben, die Schnittstelle zwischen zwei Subsystemen auszudrücken. Das hilft, die Definitionen zu lokalisieren, die für die Zwischenfunktionsfähigkeit der Subsysteme erforderlich sind, und verhindert Widersprüchlichkeiten, wenn jene Subsysteme kommunizieren.
  • Dokumentation - In ausdrucksvolleren Typ-Systemen können Typen als eine Form der Dokumentation dienen, da sie die Absicht des Programmierers illustrieren können. Zum Beispiel können Zeitstempel als ganze Zahlen vertreten werden - aber wenn ein Programmierer eine Funktion als das Zurückbringen eines Zeitstempel-Typs aber nicht bloß eines Typs der ganzen Zahl, dieses Dokumententeils der Bedeutung der Funktion erklärt.
  • Optimierung - Statische Datentypprüfung kann nützliche Übersetzungszeit-Auskunft geben. Zum Beispiel, wenn ein Typ verlangt, dass sich ein Wert im Gedächtnis an einem Vielfache von vier Bytes ausrichten muss, kann der Bearbeiter im Stande sein, effizientere Maschineninstruktionen zu verwenden.
  • Sicherheit - der Gebrauch von Typen kann einem Bearbeiter erlauben, sinnlos oder wahrscheinlich ungültiger Code zu entdecken. Zum Beispiel können wir einen Ausdruck als Invalide identifizieren, weil die Regeln der Arithmetik nicht angeben, wie man eine ganze Zahl durch eine Schnur teilt. Wie besprochen, unten, starke tippende Angebote mehr Sicherheit, aber versichert allgemein ganze Sicherheit nicht (sieh Typ-Sicherheit für mehr Information).

Starke Typ-Systeme können auch eine Kehrseite, besonders hinsichtlich des Zwingens den Programmierer haben, sich mit der unnötigen "Buchhaltung" zu beschäftigen, unnötige ausführliche Konvertierungen in Zusammenhängen zu machen, wo eine implizite Konvertierung keinen Schaden verursachen würde. Das Typ-System des Pascal ist als "zu stark" beschrieben worden, weil die Größe einer Reihe oder Schnur ein Teil seines Typs ist, einige Programmieraufgaben sehr schwierig machend.

Im Gegenteil, auf einigen Sprachen, wie Haskell, werden Typen automatisch abgeleitet, so trotz des starken Typ-Systems tippen (meiste), sind Anmerkungen unnötig.

Typ-Sicherheit trägt zu Programm-Genauigkeit bei, aber kann es nicht versichern, wenn die Datentypprüfung selbst kein unentscheidbares Problem wird. Abhängig vom spezifischen Typ-System kann ein Programm das falsche Ergebnis geben und sicher getippt werden, keine Bearbeiter-Fehler erzeugend. Zum Beispiel wird die Abteilung durch die Null durch den Typ-Kontrolleur auf den meisten Programmiersprachen nicht gefangen; stattdessen ist es ein Laufzeitfehler. Um die Abwesenheit von allgemeineren Defekten zu beweisen, sind andere Arten von formellen Methoden, die insgesamt als Programm-Analysen bekannt sind, in der üblichen Anwendung, sowie Softwareprüfung, einer weit verwendeten empirischen Methode, um Fehler zu finden, die der Typ-Kontrolleur nicht entdecken kann.

Ein Programm vereinigt normalerweise jeden Wert mit einem besonderem Typ (obwohl ein Typ mehr als einen Subtyp haben kann). Andere Entitäten, wie Gegenstände, Module, Nachrichtenkanäle, Abhängigkeiten, oder sogar Typen selbst, können verbunden mit einem Typ werden. Einige Durchführungen könnten die folgenden Identifizierungen machen (obwohl das technisch verschiedene Konzepte sind):

  • Klasse - ein Typ eines Gegenstands
  • Datentyp - ein Typ eines Werts
  • Art - ein Typ eines Typs

Ein Typ-System, das für jede Programmiersprache angegeben ist, kontrolliert getippte Programme der Wege kann sich benehmen, und macht Verhalten außerhalb dieser Regeln ungesetzlich. Ein Wirkungssystem stellt normalerweise mehr feinkörnige Kontrolle zur Verfügung, als ein Typ-System tut.

Formell studiert Typ-Theorie Typ-Systeme. Mehr wohl durchdachte Typ-Systeme (wie abhängige Typen) berücksichtigen feinere-grained durch einen Typ-Kontrolleur nachzuprüfende Programm-Spezifizierungen, aber das kommt an einem Preis, weil Typ-Schlussfolgerung und andere Eigenschaften allgemein unentscheidbar werden, und Datentypprüfung selbst von benutzergelieferten Beweisen abhängig ist. Es ist schwierig, um ein genug ausdrucksvolles Typ-System zu finden, das alle Programmiermethoden im Typ sichere Weise befriedigt. Als Mark Manasse kurz gesagt hat:

Datentypprüfung

Der Prozess des Überprüfens und Erzwingens der Einschränkungen von Typen - Datentypprüfung - kann irgendein während der Übersetzung (eine statische Kontrolle) oder Durchlaufzeit (eine dynamische Kontrolle) vorkommen. Wenn eine Sprachspezifizierung seine tippenden Regeln stark verlangt (d. h., mehr oder weniger nur jene automatischen Typ-Konvertierungen erlaubend, die Information nicht verlieren), kann man sich auf den Prozess so stark getippt, wenn nicht, wie schwach getippt, beziehen. Die Begriffe werden in einem strengen Sinn nicht gewöhnlich gebraucht.

Das statische Schreiben

Wie man

sagt, verwendet eine Programmiersprache das statische Schreiben, wenn Datentypprüfung während der Übersetzungszeit im Vergleich mit der Durchlaufzeit durchgeführt wird. Statisch getippte Sprachen schließen ActionScript 3, Ada, C, D ein, Eiffel, F#, Fortran, Gehen Haskell, haXe, JADE, Java, ML, Ziel-C, OCaml, Pascal und Scala. C ++ wird beiseite von seinem Laufzeittyp-Informationssystem statisch getippt. Das Typ-System C# führt statische Übersetzungszeit-Datentypprüfung durch, sondern auch schließt volle Laufzeitdatentypprüfung ein. Perl wird in Bezug auf das Unterscheiden der Reihe, des Kuddelmuddels, der Skalare und der Unterprogramme statisch getippt.

Das statische Schreiben ist eine beschränkte Form der Programm-Überprüfung (sieh Typ-Sicherheit): Entsprechend erlaubt es vielen Typ-Fehlern, früh im Entwicklungszyklus gefangen zu werden. Statische Typ-Kontrolleure bewerten nur die Typ-Information, die während der Übersetzung bestimmt werden kann, aber im Stande ist nachzuprüfen, dass die karierten Bedingungen für alle möglichen Ausführungen des Programms halten, das das Bedürfnis beseitigt zu wiederholen, dass Typ jedes Mal überprüft, wenn das Programm durchgeführt wird. Programm-Ausführung kann auch effizienter (z.B schneller oder Einnahme des reduzierten Gedächtnisses) durch das Auslassen von Laufzeittyp-Kontrollen und das Ermöglichen anderer Optimierungen gemacht werden.

Weil sie Typ-Information während der Kompilation bewerten und deshalb an Typ-Information Mangel haben, die nur an der Durchlaufzeit verfügbar ist, sind statische Typ-Kontrolleure konservativ. Sie werden einige Programme zurückweisen, die an der Durchlaufzeit wohl erzogen sein können, aber das kann nicht statisch beschlossen werden, gut getippt zu werden. Zum Beispiel, selbst wenn ein Ausdruck

:

wird wie schlecht-getippt, zurückgewiesen, weil eine statische Analyse nicht beschließen kann, dass der Zweig nicht genommen wird. Das konservative Verhalten von statischen Typ-Kontrolleuren ist wenn vorteilhaft

Die am weitesten verwendeten statisch getippten Sprachen sind nicht formell sicherer Typ. Sie haben "Lücken" in den Programmiersprache-Spezifizierungsermöglichen-Programmierern, um Code zu schreiben, der die Überprüfung überlistet, die durch einen statischen Typ-Kontrolleur durchgeführt ist, und so richten Sie eine breitere Reihe von Problemen. Zum Beispiel haben die meisten C-style Sprachen das Typ-Witzeln, und Haskell hat solche Eigenschaften wie: Solche Operationen können an der Durchlaufzeit unsicher sein, in der sie unerwünschtes Verhalten wegen des falschen Schreibens von Werten verursachen können, wenn das Programm läuft.

Das dynamische Schreiben

Wie man

sagt, wird eine Programmiersprache dynamisch getippt, wenn die Mehrheit seiner Datentypprüfung an der Durchlaufzeit im Vergleich mit während der Übersetzung durchgeführt wird. In dynamischen tippenden Werten haben Typen, aber Variablen tun nicht; d. h. eine Variable kann sich auf einen Wert jedes Typs beziehen. Dynamisch getippte Sprachen schließen APL, Erlang, Irre, JavaScript, Lispeln, Lua, MATLAB, GNU-Oktave, Perl (für benutzerbestimmte Typen, aber nicht eingebaute Typen), PHP, Auswahl GRUNDLEGEND, Einleitung, Pythonschlange, Rubin, Smalltalk und Tcl ein.

Durchführungen von dynamisch getippten Sprachen vereinigen allgemein Laufzeitgegenstände mit "Anhängseln", die ihre Typ-Information enthalten. Diese Laufzeitklassifikation wird dann verwendet, um Typ-Kontrollen durchzuführen, und Absendung hat Funktionen überladen, aber kann auch durchdringenden Gebrauch der dynamischen Absendung ermöglichen, spät bindend und ähnlichen Idiome, die an am besten auf einer statisch getippten Sprache beschwerlich sein würden, den Gebrauch von verschiedenen Typen oder ähnlichen Eigenschaften verlangend.

Weit gehender, wie erklärt, unten, kann das dynamische Schreiben Unterstützung für dynamische Programmiersprache-Eigenschaften, wie das Erzeugen von Typen und auf Laufzeitdaten gestützter Funktionalität verbessern. (Dennoch brauchen dynamisch getippte Sprachen keinen oder alle diese Eigenschaften zu unterstützen, und einige dynamische Programmiersprachen werden statisch getippt.) Andererseits stellt das dynamische Schreiben weniger a priori Garantien zur Verfügung: Eine dynamisch getippte Sprache akzeptiert und versucht, einige Programme durchzuführen, über die als Invalide durch einen statischen Typ-Kontrolleur entweder wegen Fehler im Programm oder wegen der statischen Datentypprüfung geherrscht würde, die zu konservativ ist.

Das dynamische Schreiben kann auf Laufzeittyp-Fehler — d. h. an der Durchlaufzeit hinauslaufen, ein Wert kann einen unerwarteten Typ haben, und eine für diesen Typ sinnlose Operation wird angewandt. Solche Fehler können vorkommen lange nach dem Platz, wo der Programmierfehler gemacht wurde — d. h. der Platz, wo der falsche Typ von Daten in einen Platz gegangen ist, sollte er nicht haben. Das kann den Programmfehler schwierig machen sich niederzulassen.

Dynamisch getippte Sprachsystemlaufzeitkontrollen können potenziell hoch entwickelter sein als diejenigen statisch getippter Sprachen, weil sie dynamische Information sowie jede Information aus dem Quellcode verwenden können. Andererseits überprüft Durchlaufzeit nur behaupten, dass Bedingungen in einer besonderen Ausführung des Programms halten, und die Kontrollen für jede Ausführung des Programms wiederholt werden.

Die Entwicklung auf dynamisch getippten Sprachen wird häufig durch die Programmierung von Methoden wie Einheitsprüfung unterstützt. Prüfung ist eine Schlüsselpraxis in der Berufssoftwareentwicklung, und ist auf dynamisch getippten Sprachen besonders wichtig. In der Praxis kann die Prüfung, die getan ist, um richtige Programm-Operation zu sichern, eine viel breitere Reihe von Fehlern entdecken als statische Datentypprüfung, aber der volle Testeinschluss über alle möglichen Ausführungen eines Programms (einschließlich des Timings, Benutzereingänge, usw.), wenn sogar möglich, würde äußerst kostspielig und unpraktisch sein. Das statische Schreiben hilft durch die Versorgung starker Garantien einer besonderen Teilmenge von allgemein gemachten Fehlern, die nie vorkommen

Kombinationen des dynamischen und statischen Schreibens

Die Anwesenheit des statischen Schreibens auf einer Programmiersprache bezieht die Abwesenheit aller dynamischen tippenden Mechanismen nicht notwendigerweise ein. Zum Beispiel, Java und einige andere scheinbar statisch getippte Sprachen, unterstützen Sie downcasting und andere Typ-Operationen, die von Laufzeittyp-Kontrollen, einer Form des dynamischen Schreibens abhängen. Mehr allgemein schließen die meisten Programmiersprachen Mechanismen ein, um über verschiedene 'Arten' von Daten, wie zusammenhanglose Vereinigungen, polymorphe Gegenstände und verschiedene Typen zu entsenden: Selbst wenn nicht aufeinander zu wirken, Anmerkungen oder Datentypprüfung tippt, sind solche Mechanismen dynamischen tippenden Durchführungen materiell ähnlich. Sieh Programmiersprache für mehr Diskussion der Wechselwirkungen zwischen dem statischen und dynamischen Schreiben.

Bestimmte Sprachen, zum Beispiel Clojure oder Cython, werden standardmäßig dynamisch getippt, aber erlauben diesem Verhalten, durch den Gebrauch von ausführlichen Typ-Hinweisen überritten zu werden, die auf das statische Schreiben hinauslaufen. Ein Grund, solche Hinweise zu verwenden, würde die Leistungsvorteile des statischen Schreibens in mit der Leistung empfindlichen Teilen des Codes erreichen sollen.

Bezüglich der 4.0 Ausgabe unterstützt das.NET Fachwerk eine Variante des dynamischen Schreibens über das System. Dynamischer namespace, wodurch ein statischer Gegenstand 'des dynamischen' Typs ein Platzhalter für die.NET Durchlaufzeit ist, um seine dynamischen Möglichkeiten zu befragen, die Gegenstand-Verweisung aufzulösen.

Statische und dynamische Datentypprüfung in der Praxis

Die Wahl zwischen dem statischen und dynamischen Schreiben verlangt Umtausche.

Das statische Schreiben kann Typ-Fehler zuverlässig während der Übersetzung finden. Das sollte die Zuverlässigkeit des gelieferten Programms vergrößern. Jedoch stimmen Programmierer darüber nicht überein, wie allgemein Typ-Fehler vorkommen, und so über das Verhältnis jener Programmfehler nicht übereinstimmen, die codiert werden, der durch das passende Darstellen der bestimmten Typen im Code gefangen würde. Statische tippende Verfechter glauben, dass Programme zuverlässiger sind, als sie gut Typ-kariert gewesen sind, während dynamische tippende Verfechter zum verteilten Code hinweisen, der sich zuverlässig und kleinen Programmfehler-Datenbanken erwiesen hat. Der Wert des statischen Schreibens nimmt dann vermutlich zu, wie die Kraft des Typ-Systems vergrößert wird. Verfechter abhängig getippter Sprachen wie Abhängiger ML und Sinngedicht haben vorgeschlagen, dass fast alle Programmfehler als Typ-Fehler betrachtet werden können, wenn die in einem Programm verwendeten Typen vom Programmierer richtig erklärt oder richtig durch den Bearbeiter abgeleitet werden.

Das statische Schreiben läuft gewöhnlich auf kompilierten Code hinaus, der schneller durchführt. Wenn der Bearbeiter die genauen Datentypen weiß, die im Gebrauch sind, kann er optimierten Maschinencode erzeugen. Weiter können Bearbeiter für statisch getippte Sprachen Assemblerabkürzungen leichter finden. Einige dynamisch getippte Sprachen wie Allgemeines Lispeln erlauben fakultative Typ-Behauptungen für die Optimierung aus diesem wirklichen Grund. Das statische Schreiben macht das durchdringend. Sieh Optimierung.

Im Vergleich kann das dynamische Schreiben Bearbeitern erlauben, schneller zu laufen und Dolmetschern zu erlauben, neuen Code dynamisch zu laden, da Änderungen zum Quellcode auf dynamisch getippten Sprachen auf weniger Überprüfung hinauslaufen können, um zu leisten, und weniger Code, um wieder zu besuchen. Das kann auch abnehmen das Editieren kompilieren Testfehlersuchprogramm-Zyklus.

Statisch getippte Sprachen, die an Typ-Schlussfolgerung Mangel haben (wie C und Java) verlangen, dass Programmierer die Typen erklären, die sie eine Methode oder Funktion beabsichtigen zu verwenden. Das kann als zusätzliche Dokumentation für das Programm dienen, das der Bearbeiter dem Programmierer nicht erlauben wird, zu ignorieren oder zu erlauben, aus der Synchronisation zu treiben. Jedoch kann eine Sprache statisch getippt werden, ohne Typ-Behauptungen zu verlangen (Beispiele schließen Haskell, Scala und in einem kleineren Ausmaß C# ein), so ist ausführliche Typ-Behauptung nicht eine notwendige Voraussetzung für das statische Schreiben auf allen Sprachen.

Das dynamische Schreiben erlaubt Konstruktionen, die etwas statische Datentypprüfung als ungesetzlich zurückweisen würde. Zum Beispiel, eval Funktionen, die willkürliche Daten als Code, werden möglich durchführen. Eine Eval-Funktion ist mit dem statischen Schreiben möglich, aber verlangt fortgeschrittenen Gebrauch von algebraischen Datentypen. Außerdem passt das dynamische Schreiben besser Übergangscode und prototyping, wie das Erlauben einer Platzhalter-Datenstruktur (nachgemachter Gegenstand) an, um im Platz einer flüggen Datenstruktur (gewöhnlich zu den Zwecken des Experimentierens und der Prüfung) durchsichtig verwendet zu werden.

Das dynamische Schreiben wird in der Ente verwendet, die tippt, der leichteren Codewiedergebrauch unterstützen kann.

Das dynamische Schreiben macht normalerweise metaprogramming wirksamer und leichter zu verwenden. Zum Beispiel C ++ sind Schablonen normalerweise beschwerlicher, um zu schreiben, als der gleichwertige Ruby oder Pythonschlange-Code. Fortgeschrittenere Laufzeitkonstruktionen wie metaclasses und Selbstbeobachtung sind häufig schwieriger, auf statisch getippten Sprachen zu verwenden. Auf einigen Sprachen können solche Eigenschaften auch z.B verwendet, um neue Typen und Handlungsweisen im Fluge zu erzeugen, auf Laufzeitdaten gestützt werden. Solche fortgeschrittenen Konstruktionen werden häufig durch dynamische Programmiersprachen zur Verfügung gestellt; viele von diesen werden dynamisch getippt, obwohl dynamisch tippend mit dynamischen Programmiersprachen nicht verbunden zu sein braucht.

Das starke und schwache Schreiben: Definition von Liskov

1974 haben Jones und Liskov eine stark getippte Sprache als diejenige beschrieben, in der "jeder Typ eine Reihe primitiver Operationen definiert, die die einzigen direkten Mittel sind, um Gegenstände dieses Typs zu manipulieren."

Jackson hat geschrieben, "Auf einer stark getippten Sprache wird jedes Datengebiet einen verschiedenen Typ haben und jeder Prozess seine Nachrichtenvoraussetzungen in Bezug auf diese Typen festsetzen wird."

Das starke und schwache Schreiben

Wie man

sagt, zeigt ein Typ-System das starke Schreiben, wenn es eine oder mehr Beschränkungen dessen angibt, wie Operationen, die mit Werten verschiedener Datentypen verbunden sind, vermischt werden können. Eine Computersprache, die das starke Schreiben durchführt, wird die erfolgreiche Ausführung einer Operation auf Argumenten verhindern, die den falschen Typ haben.

Schwach tippend bedeutet, dass eine Sprache implizit (oder Würfe) Typen, wenn verwendet, umwandelt. Denken Sie das folgende Beispiel:

var x: = 5;//(1) (x ist eine ganze Zahl)

var y: = "37";//(2) (y ist eine Schnur)

x + y;//(3)(?)

Auf einer schwach getippten Sprache hängt das Ergebnis dieser Operation von sprachspezifischen Regeln ab. Visuell Grundlegend würde die Schnur "37" in die Nummer 37 umwandeln, Hinzufügung durchführen, und die Nummer 42 erzeugen. JavaScript würde die Nummer 5 zur Schnur "5" umwandeln, Schnur-Verkettung durchführen, und die Schnur "537" erzeugen. In JavaScript wird die Konvertierung zur Schnur unabhängig von der Ordnung des operands angewandt (zum Beispiel, y + würde x "375" sein), während in AppleScript ganz links operand den Typ des Ergebnisses bestimmt, so dass x + y die Nummer 42 aber y + x ist, ist die Schnur "375".

Auf dieselbe Weise, wegen der dynamischen Typ-Konvertierungen von JavaScript:

var y = 2 / 0;//y kommt jetzt einer Konstante für die Unendlichkeit gleich

y = = Zahl. POSITIVE_INFINITY//gibt wahren zurück

Unendlichkeit == Zahl. POSITIVE_INFINITY//gibt wahren zurück

"Unendlichkeit" == Unendlichkeit//gibt wahren zurück

y = = gibt "Unendlichkeit"//wahren zurück

</Quelle>

Ein C hat sich schief gegangen geworfen veranschaulicht die Probleme, die vorkommen können, wenn das starke Schreiben fehlt: Wenn ein Programmierer einen Wert von einem Typ bis einen anderen in C, nicht wirft, muss nur der Bearbeiter den Code während der Übersetzung erlauben, aber die Durchlaufzeit muss es ebenso erlauben. Das kann kompakteren und schnelleren C-Code erlauben, aber er kann das Beseitigen schwieriger machen.

Sicher und unsicher getippte Systeme

Eine dritte Weise, das Typ-System einer Programmiersprache zu kategorisieren, verwendet die Sicherheit von getippten Operationen und Konvertierungen. Computerwissenschaftler betrachten eine Sprache als "vor dem Typ sicher", wenn sie Operationen oder Konvertierungen nicht erlaubt, die zu falschen Bedingungen führen.

Einige Beobachter gebrauchen den Begriff speichersichere Sprache (oder gerade sichere Sprache), um Sprachen zu beschreiben, die unbestimmten Operationen nicht erlauben vorzukommen. Zum Beispiel wird eine speichersichere Sprache Reihe-Grenzen überprüfen, oder statisch versichern (d. h., während der Übersetzung vor der Ausführung), dass Reihe-Zugänge aus den Reihe-Grenzen Übersetzungszeit und vielleicht Laufzeitfehler verursachen werden.

var x: = 5;//(1)

var y: = "37";//(2)

var z: = x + y;//(3)

</Quelle>

Auf Sprachen wie Visueller, der Grundlegend, im Beispiel variabel ist, erwirbt den Wert 42. Während der Programmierer kann oder das nicht beabsichtigt haben kann, definiert die Sprache das Ergebnis spezifisch, und das Programm zertrümmert nicht oder teilt einen schlecht-definierten Wert dem zu. In dieser Beziehung sind solche Sprachen vor dem Typ sicher; jedoch, auf einigen Sprachen, wenn der Wert dessen eine Schnur war, die zu einer Zahl (z.B "Hallo Welt") nicht umgewandelt werden konnte, würden die Ergebnisse unbestimmt sein. Solche Sprachen sind vor dem Typ sicher (in dem sie nicht abstürzen werden), aber kann unerwünschte Ergebnisse leicht erzeugen. Auf anderen Sprachen wie JavaScript würde der numerische operand zu einer Schnur, und dann durchgeführter Verkettung umgewandelt. In diesem Fall sind die Ergebnisse nicht unbestimmt und sind voraussagbar.

Lassen Sie uns jetzt auf dasselbe Beispiel in C schauen:

interne Nummer x = 5;

Rotforelle y [] = "37";

char* z = x + y;

</Quelle>

In diesem Beispiel wird auf eine Speicheradresse fünf Charaktere darüber hinaus, gleichwertig zu drei Charakteren anspitzen, nachdem der endende Nullcharakter der Schnur zu dadurch hingewiesen hat. Der Inhalt dieser Position ist unbestimmt, und könnte draußen addressable Gedächtnis liegen. Die bloße Berechnung solch eines Zeigestocks kann auf unbestimmtes Verhalten (einschließlich des Programm-Unfalls) gemäß C Standards hinauslaufen, und in typischen Systemen dereferencing z an diesem Punkt konnte das Programm veranlassen abzustürzen. Wir haben einen gut getippten, aber nicht speichersicheres Programm — eine Bedingung, die auf einer vor dem Typ sicheren Sprache nicht vorkommen kann.

Auf einigen Sprachen, wie JavaScript, erlaubt der Gebrauch von speziellen numerischen Werten und Konstanten Typ-Sicherheit für mathematische Operationen, ohne auf Laufzeitfehler hinauszulaufen. Zum Beispiel, wenn man sich durch a, oder durch die Null teilt.

var x = 32;

var aString = neue Schnur ("A");

x = x/aString;//x kommt jetzt unveränderlichem NaN gleich, Nicht Eine Zahl bedeutend

isNaN (x);//gibt wahren zurück

typeof (x);//gibt "Zahl" zurück

var y = 2 / 0;//y kommt jetzt einer Konstante für die Unendlichkeit gleich

y = = Zahl. POSITIVE_INFINITY;//gibt wahren zurück

typeof (y);//gibt "Zahl" zurück

</Quelle>

Variable Niveaus der Datentypprüfung

Einige Sprachen erlauben verschiedenen Niveaus der Überprüfung, für verschiedene Gebiete des Codes zu gelten. Beispiele include: -

  • Die Direktive in Perl wendet stärkere Überprüfung an.
  • Der Maschinenbediener in PHP unterdrückt einige Fehlermeldungen.
  • Darin erlaubt VB.NET dem Bearbeiter, eine Konvertierung zwischen Gegenständen zu verlangen.

Zusätzliche Werkzeuge wie Scharpie und IBM Rational Purify können auch verwendet werden, um ein höheres Niveau der Strenge zu erreichen.

Fakultative Typ-Systeme

Es ist hauptsächlich von Gilad Bracha vorgeschlagen worden, dass die Wahl des Typ-Systems unabhängig der Wahl der Sprache gemacht wird; dass ein Typ-System ein Modul das sein sollte

kann in eine Sprache, wie erforderlich, "zugestopft" werden. Er glaubt, dass das vorteilhaft ist, weil, was er obligatorische Typ-Systeme nennt, Sprachen weniger ausdrucksvoll machen und zerbrechlicher codieren. Die Voraussetzung, dass Typen die Semantik der Sprache nicht betreffen, ist schwierig zu erfüllen: Zum Beispiel wird gestütztes Erbe der Klasse unmöglich.

Polymorphism und Typen

Der Begriff "polymorphism" bezieht sich auf die Fähigkeit des Codes (insbesondere Methoden oder Klassen), um Werten vielfacher Typen, oder zur Fähigkeit von verschiedenen Beispielen derselben Datenstruktur zu folgen, um Elemente von verschiedenen Typen zu enthalten. Typ-Systeme, die polymorphism allgemein erlauben, tun so, um das Potenzial für den Codewiedergebrauch zu verbessern: Auf einer Sprache mit polymorphism müssen Programmierer nur eine Datenstruktur wie eine Liste oder eine assoziative Reihe einmal, aber nicht einmal für jeden Typ des Elements durchführen, mit dem sie planen, es zu verwenden. Aus diesem Grund nennen Computerwissenschaftler manchmal den Gebrauch von bestimmten Formen der polymorphism allgemeinen Programmierung. Die mit dem Typ theoretischen Fundamente von polymorphism sind nah mit denjenigen der Abstraktion, der Modularität und (in einigen Fällen) des Subschreibens verbunden.

Das Ente-Schreiben

Im "Ente-Schreiben" verlässt sich eine Behauptung, die eine Methode auf einem Gegenstand nennt, auf den offen erklärten Typ des Gegenstands nicht; nur dass der Gegenstand, beliebigen Typs, eine Durchführung der Methode genannt, wenn genannt, an der Durchlaufzeit liefern muss.

Das Ente-Schreiben unterscheidet sich vom Strukturschreiben darin, wenn der Teil (der ganzen Modul-Struktur) erforderlich für eine gegebene lokale Berechnung an der Durchlaufzeit da ist, ist das Ente-Typ-System in seiner Typ-Identitätsanalyse zufrieden. Andererseits würde ein Strukturtyp-System verlangen, dass die Analyse der ganzen Modul-Struktur während der Übersetzung Typ-Identität oder Typ-Abhängigkeit bestimmt.

Das Ente-Schreiben unterscheidet sich von einem Nominativtyp-System in mehreren Aspekten. Die prominentesten sind, dass für das Ente-Schreiben Typ-Information an der Durchlaufzeit (im Gegensatz zur Übersetzungszeit) bestimmt wird, und der Name des Typs irrelevant ist, um Typ-Identität oder Typ-Abhängigkeit zu bestimmen; nur teilweise Struktur-Information ist dafür für einen gegebenen Punkt in der Programm-Ausführung erforderlich.

Ente, die tippt, verwendet die Proposition, dass (sich auf einen Wert beziehend), "wenn sie wie eine Ente und Quacksalber wie eine Ente dann spazieren geht, es eine Ente" ist (das ist eine Verweisung auf den Ente-Test, der James Whitcomb Riley zugeschrieben wird). Der Begriff kann von Alex Martelli in einer 2000-Nachricht an den comp.lang.python newsgroup ins Leben gerufen worden sein (sieh Pythonschlange).

Spezialtyp-Systeme

Viele Typ-Systeme sind geschaffen worden, die für den Gebrauch in bestimmten Umgebungen mit bestimmten Typen von Daten, oder für die statische Programm-Analyse aus dem Band spezialisiert werden. Oft basieren diese auf Ideen aus der formellen Typ-Theorie und sind nur als ein Teil von Prototyp-Forschungssystemen verfügbar.

Abhängige Typen

Abhängige Typen basieren auf der Idee, Skalare zu verwenden, oder schätzt, um den Typ eines anderen Werts genauer zu beschreiben. Zum Beispiel, könnte der Typ 3&times;3 Matrix sein. Wir können dann tippende Regeln wie die folgende Regel für die Matrixmultiplikation definieren:

wo willkürliche positive Werte der ganzen Zahl sind. Eine Variante von ML genannt Abhängiger ML ist gestützt auf diesem Typ-System geschaffen worden, aber weil die Datentypprüfung für herkömmliche abhängige Typen, nicht unentscheidbar ist, können alle Programme mit ihnen ohne eine Art Grenzen Typ-kariert sein. Abhängiger ML beschränkt die Sorte der Gleichheit, die es zur Arithmetik von Presburger entscheiden kann. Andere Sprachen wie Sinngedicht machen den Wert aller Ausdrücke auf der Sprache entscheidbar, so dass Datentypprüfung entscheidbar sein kann. Es ist auch möglich, die Sprache Turing-abgeschlossen zum Preis der unentscheidbaren Datentypprüfung, als im Cayennepfeffer zu machen.

Geradlinige Typen

Geradlinige Typen, die auf der Theorie der geradlinigen Logik gestützt sind, und nah mit Einzigartigkeitstypen verbunden sind, sind Typen, die Werten zugeteilt sind, die das Eigentum haben, dass sie eine und nur eine Verweisung auf sie zu jeder Zeit haben. Diese sind wertvoll, um große unveränderliche Werte wie Dateien, Schnuren und so weiter zu beschreiben, weil jede Operation, die gleichzeitig einen geradlinigen Gegenstand zerstört und einen ähnlichen Gegenstand schafft (solcher als'') "unter der Motorhaube" in eine Veränderung im Platz optimiert werden kann. Normalerweise ist das nicht möglich, weil solche Veränderungen Nebenwirkungen auf Teilen des Programms verursachen konnten, das andere Verweisungen auf den Gegenstand hält, Verweisungsdurchsichtigkeit verletzend. Sie werden auch im Prototyp Betriebssystemeigenartigkeit für die Zwischenprozess-Kommunikation verwendet, statisch sicherstellend, dass Prozesse Gegenstände im geteilten Gedächtnis nicht teilen können, um Rasse-Bedingungen zu verhindern. Die Saubere Sprache (eine Haskell ähnliche Sprache) verwendet dieses Typ-System, um viel Geschwindigkeit zu gewinnen, während er sicher bleibt.

Kreuzungstypen

Kreuzungstypen sind Typen, die Werte beschreiben, die beiden von zwei anderen gegebenen Typen mit überlappenden Wertsätzen gehören. Zum Beispiel in den meisten Durchführungen von C hat die unterzeichnete Rotforelle Reihe-128 zu 127, und die nicht unterzeichnete Rotforelle hat Reihe 0 bis 255, so würde der Kreuzungstyp dieser zwei Typen Reihe 0 bis 127 haben. Solch ein Kreuzungstyp konnte in Funktionen sicher passiert werden, die entweder unterzeichnete oder nicht unterzeichnete Rotforellen erwarten, weil es mit beiden Typen vereinbar ist.

Kreuzungstypen sind nützlich, um überladene Funktionstypen zu beschreiben: Zum Beispiel, wenn "" der Typ von Funktionen ist, die ein Argument der ganzen Zahl nehmen und eine ganze Zahl zurückgeben, und "" der Typ von Funktionen ist, die ein Argument der Hin- und Herbewegung nehmen und eine Hin- und Herbewegung zurückgeben, dann kann die Kreuzung dieser zwei Typen verwendet werden, um Funktionen zu beschreiben, die ein oder der andere tun, der darauf gestützt ist, welcher eingegeben ihnen gegeben wird. Solch eine Funktion konnte in eine andere Funktion passiert werden, eine ""-Funktion sicher erwartend; es würde einfach die "" Funktionalität nicht verwenden.

In einer Subklassifizieren-Hierarchie ist die Kreuzung eines Typs und eines Vorfahr-Typs (wie sein Elternteil) der am meisten abgeleitete Typ. Die Kreuzung von Geschwister-Typen ist leer.

Die Sprache von Forsythe schließt eine allgemeine Durchführung von Kreuzungstypen ein. Eine eingeschränkte Form ist Verbesserungstypen.

Vereinigungstypen

Vereinigungstypen sind Typen, die Werte beschreiben, die jedem von zwei Typen gehören. Zum Beispiel, in C, hat die unterzeichnete Rotforelle Reihe-128 zu 127, und die nicht unterzeichnete Rotforelle hat Reihe 0 bis 255, so würde die Vereinigung dieser zwei Typen Reihe-128 zu 255 haben. Jede Funktion, die diesen Vereinigungstyp behandelt, würde sich mit ganzen Zahlen in dieser ganzen Reihe befassen müssen. Mehr allgemein sind die einzigen gültigen Operationen auf einem Vereinigungstyp Operationen, die auf beiden Typen gültig sind, die unioned sind. Das "Vereinigungs"-Konzept von C ist Vereinigungstypen ähnlich, aber ist nicht typesafe, weil es Operationen erlaubt, die auf jedem Typ, aber nicht beiden gültig sind. Vereinigungstypen sind in der Programm-Analyse wichtig, wo sie verwendet werden, um symbolische Werte zu vertreten, deren genaue Natur (z.B, Wert oder Typ) nicht bekannt ist.

In einer Subklassifizieren-Hierarchie ist die Vereinigung eines Typs und eines Vorfahr-Typs (wie sein Elternteil) der Vorfahr-Typ. Die Vereinigung von Geschwister-Typen ist ein Subtyp ihres gemeinsamen Ahnen (d. h. alle auf ihrem gemeinsamen Ahnen erlaubten Operationen werden auf dem Vereinigungstyp erlaubt, aber sie können auch andere gültige Operationen gemeinsam haben).

Existenzielle Typen

Existenzielle Typen werden oft im Zusammenhang mit Rekordtypen verwendet, um Module und abstrakte Datentypen wegen ihrer Fähigkeit zu vertreten, Durchführung von der Schnittstelle zu trennen. Zum Beispiel beschreibt der Typ "T = X { a: X; f: (X &rarr; int); }" eine Modul-Schnittstelle, die ein Datenmitglied des Typs X und einer Funktion hat, die einen Parameter desselben Typs X nimmt und eine ganze Zahl zurückgibt. Das konnte unterschiedlich durchgeführt werden; zum Beispiel:

  • intT = {a: interne Nummer; f: (interne Nummer  interne Nummer); }\
  • floatT = {a: Hin- und Herbewegung; f: (Lassen Sie  interne Nummer schwimmen); }\

Diese Typen sind beide Subtypen des allgemeineren existenziellen Typs T und entsprechen konkreten Durchführungstypen, so ist jeder Wert von einem dieser Typen ein Wert des Typs T. In Anbetracht eines Werts "t" des Typs "T" wissen wir, dass "t.f (t.a)", unabhängig davon gut getippt wird, wie der abstrakte Typ X ist. Das gibt Flexibilität, um einer besonderen Durchführung angepasste Typen zu wählen, während Kunden, die nur Werte des Schnittstelle-Typs - des existenziellen Typs verwenden - von diesen Wahlen isoliert werden.

Im Allgemeinen ist es für den typechecker unmöglich abzuleiten, welchem existenziellem Typ ein gegebenes Modul gehört. Im obengenannten Beispiel intT {a: interne Nummer; f: (interne Nummer  interne Nummer);} konnte auch den Typ X {a haben: X; f: (interne Nummer  interne Nummer);}. Die einfachste Lösung ist, jedes Modul mit seinem beabsichtigten Typ z.B zu kommentieren:

  • intT = {a: interne Nummer; f: (interne Nummer  interne Nummer);} als X {a: X; f: (X  interne Nummer); }\

Obwohl abstrakte Datentypen und Module auf Programmiersprachen eine Zeit lang erst als 1988 durchgeführt worden waren, dass John C. Mitchell und Gordon Plotkin die formelle Theorie unter dem Slogan eingesetzt haben: "Auszug [Daten] Typen hat existenziellen Typ". Die Theorie ist getippte Lambda-Rechnung einer zweiten Ordnung, die dem System F, aber mit dem existenziellen statt der universalen Quantifizierung ähnlich ist.

Ausführliche oder implizite Behauptung und Schlussfolgerung

Viele statische Typ-Systeme, wie diejenigen von C und Java, verlangen Typ-Behauptungen: Der Programmierer muss jede Variable mit einem besonderen Typ ausführlich vereinigen. Andere, wie Haskell, führen Typ-Schlussfolgerung durch: Der Bearbeiter zieht Schlüsse über die Typen von Variablen, die darauf gestützt sind, wie Programmierer jene Variablen verwenden. Zum Beispiel in Anbetracht einer Funktion, die beiträgt und zusammen, kann der Bearbeiter ableiten, dass und Zahlen sein muss - da Hinzufügung nur für Zahlen definiert wird. Deshalb würde jeder Anruf anderswohin im Programm, das einen nichtnumerischen Typ (wie eine Schnur oder Liste) als ein Argument angibt, einem Fehler Zeichen geben.

Numerisch und Schnur-Konstanten und Ausdrücke im Code kann und häufig Typ in einem besonderen Zusammenhang einbeziehen. Zum Beispiel könnte ein Ausdruck einen Typ des Schwimmpunkts einbeziehen, während eine Liste von ganzen Zahlen - normalerweise eine Reihe einbeziehen könnte.

Typ-Schlussfolgerung ist im Allgemeinen möglich, wenn es in der fraglichen Typ-Theorie entscheidbar ist. Außerdem, selbst wenn Schlussfolgerung im Allgemeinen für eine gegebene Typ-Theorie unentscheidbar ist, ist Schlussfolgerung häufig für eine große Teilmenge von wirklichen Programmen möglich. Das Typ-System von Haskell, eine Version von Hindley-Milner, ist eine Beschränkung des Systems Fω zur so genannten Reihe 1 polymorphe Typen, in denen Typ-Schlussfolgerung entscheidbar ist. Die meisten Bearbeiter von Haskell erlauben willkürliche Reihe polymorphism als eine Erweiterung, aber das macht Typ-Schlussfolgerung unentscheidbar. (Datentypprüfung ist jedoch entscheidbar, und reihen Sie sich auf 1 Programme haben noch Typ-Schlussfolgerung; höhere Reihe polymorphe Programme, wird wenn nicht gegeben, ausführliche Typ-Anmerkungen zurückgewiesen.)

Typen von Typen

Ein Typ von Typen ist eine Art. Arten erscheinen ausführlich in der Typeful-Programmierung wie ein Typ-Konstrukteur auf der Sprache von Haskell.

Typen fallen in mehrere breite Kategorien:

  • Primitive Typen - die einfachste Art des Typs; z.B, ganze Zahl und Schwimmpunkt-Zahl
  • Boolean
  • Integrierte Typen - Typen von ganzen Zahlen; z.B, ganze Zahlen und natürliche Zahlen
  • Das Schwimmen von Punkt-Typen - Typen von Zahlen in der Schwimmpunkt-Darstellung
  • Bezugstypen
  • Auswahl-Typen
  • Typen von Nullable
  • Zerlegbare Typen - Typen haben von grundlegenden Typen gedichtet; z.B, Reihe oder Aufzeichnungen.
  • :Abstract-Datentypen
  • Algebraische Typen
  • Subtyp
  • Abgeleiteter Typ
  • Objektarten; z.B, Typ-Variable
  • Teilweiser Typ
  • Rekursiver Typ
  • Funktionstypen; z.B, binäre Funktionen
  • allgemein gemessene Typen, wie parametrisierte Typen
  • existenziell gemessene Typen, wie Module
  • Verbesserungstypen - Typen, die Teilmengen anderer Typen identifizieren
  • Abhängige Typen - Typen, die von Begriffen (Werte) abhängen
  • Eigentumsrecht-Typen - Typen, die beschreiben oder die Struktur von objektorientierten Systemen beschränken
  • Vorherbestimmte Typen haben für Bequemlichkeit in wirklichen Anwendungen, wie Datum, Zeit und Geld gesorgt.

Vereinigtes Typ-System

Einige Sprachen wie C# haben ein vereinigtes Typ-System. Das bedeutet, dass alle Typen C# einschließlich primitiver Typen von einem einzelnen Wurzelgegenstand erben. JederC# eintippen, erbt von der Gegenstand-Klasse. Java hat mehrere primitive Typen, die nicht Gegenstände sind. Java stellt Streifband-Objektarten zur Verfügung, die zusammen mit den primitiven Typen bestehen, so können Entwickler entweder die Streifband-Objektarten oder den einfacheren Nichtgegenstand primitive Typen verwenden.

Vereinbarkeit: Gleichwertigkeit und das Subschreiben

Ein Typ-Kontrolleur für eine statisch getippte Sprache muss nachprüfen, dass der Typ jedes Ausdrucks mit dem Typ im Einklang stehend ist, der durch den Zusammenhang erwartet ist, in dem dieser Ausdruck erscheint. Zum Beispiel, in einem Zuweisungsbefehl der Form,

der abgeleitete Typ des Ausdrucks muss mit dem offen erklärten oder abgeleiteten Typ der Variable im Einklang stehend sein. Dieser Begriff der Konsistenz, genannt Vereinbarkeit, ist in jede Programmiersprache spezifisch.

Wenn der Typ und der Typ dessen dasselbe sind und Anweisung für diesen Typ erlaubt wird, dann ist das ein gültiger Ausdruck. In den einfachsten Typ-Systemen, deshalb, nimmt die Frage dessen, ob zwei Typen vereinbar sind, ab, diesem von ob sie}} (oder gleichwertig) gleich sind. Verschiedene Sprachen haben jedoch verschiedene Kriterien dafür, wenn, wie man versteht, zwei Typ-Ausdrücke denselben Typ anzeigen. Diese verschiedenen equational Theorien}} Typen ändern sich weit, zwei äußerste Fälle, die Strukturtyp-Systeme sind, in denen irgendwelche zwei Typen gleichwertig sind, die Werte mit derselben Struktur und Nominativtyp-Systeme beschreiben, in denen keine zwei syntaktisch verschiedenen Typ-Ausdrücke denselben Typ anzeigen (d. h. müssen Typen denselben "Namen" haben, um gleich zu sein).

Auf Sprachen mit dem Subschreiben ist die Vereinbarkeitsbeziehung komplizierter. Insbesondere wenn ein Subtyp dessen ist, dann kann ein Wert des Typs in einem Zusammenhang verwendet werden, wo einer des Typs erwartet wird, selbst wenn die Rückseite nicht wahr ist. Wie Gleichwertigkeit wird die Subtyp-Beziehung verschieden für jede Programmiersprache mit vielen möglichen Schwankungen definiert. Die Anwesenheit parametrischen oder Ad-Hoc-polymorphism auf einer Sprache kann auch Implikationen für die Typ-Vereinbarkeit haben.

Programmierung des Stils

Einige Programmierer bevorzugen statisch getippte Sprachen; andere bevorzugen dynamisch getippte Sprachen. Statisch getippte Sprachen alarmieren Programmierer, um Fehler während der Kompilation zu tippen, und sie können besser an der Durchlaufzeit leisten. Verfechter dynamisch getippter Sprachen behaupten, dass sie besser schnellen prototyping unterstützen und dieser Typ Fehler nur eine kleine Teilmenge von Fehlern in einem Programm sind. Ebenfalls gibt es häufig kein Bedürfnis, alle Typen auf statisch getippten Sprachen mit der Typ-Schlussfolgerung manuell zu erklären; so wird das Bedürfnis nach dem Programmierer, Typen von Variablen ausführlich anzugeben, für solche Sprachen automatisch gesenkt; und einige dynamische Sprachen haben Durchlaufzeit optimisers, der schnellen Code erzeugen kann, der sich der Geschwindigkeit von statischen Sprachbearbeitern, häufig durch das Verwenden teilweiser Typ-Schlussfolgerung nähert.

Siehe auch

  • Typ herrscht
über

Weiterführende Literatur


Privoxy / Germantown, Virginia
Impressum & Datenschutz