Quelle est la différence entre une langue fortement typée et une langue typée statiquement?

Réponses:

543

Quelle est la différence entre une langue fortement typée et une langue typée statiquement?

Un langage typé statiquement a un système de type qui est vérifié au moment de la compilation par l'implémentation (un compilateur ou un interprète). La vérification de type rejette certains programmes et les programmes qui réussissent la vérification sont généralement assortis de certaines garanties; par exemple, le compilateur garantit de ne pas utiliser d'instructions arithmétiques entières sur les nombres à virgule flottante.

Il n'y a pas vraiment d'accord sur ce que signifie "fortement typé", bien que la définition la plus largement utilisée dans la littérature professionnelle soit que dans un langage "fortement typé", il n'est pas possible pour le programmeur de contourner les restrictions imposées par le système de type . Ce terme est presque toujours utilisé pour décrire des langages typés statiquement.

Statique vs dynamique

L’opposé du type statique est "typé dynamiquement", ce qui signifie que

  1. Les valeurs utilisées au moment de l'exécution sont classées en types.
  2. Il existe des restrictions sur la façon dont ces valeurs peuvent être utilisées.
  3. Lorsque ces restrictions sont violées, la violation est signalée comme une erreur de type (dynamique).

Par exemple, Lua , un langage typé dynamiquement, a un type de chaîne, un type de nombre et un type booléen, entre autres. Dans Lua, chaque valeur appartient à exactement un type, mais ce n'est pas une exigence pour toutes les langues typées dynamiquement. Dans Lua, il est permis de concaténer deux chaînes, mais il n'est pas permis de concaténer une chaîne et un booléen.

Fort vs faible

L'opposé de "fortement typé" est "faiblement typé", ce qui signifie que vous pouvez contourner le système de typage. C est notoirement faiblement typé car tout type de pointeur est convertible en tout autre type de pointeur simplement par transtypage. Pascal devait être fortement typé, mais une erreur de conception (enregistrements de variantes non marquées) a introduit une faille dans le système de type, donc techniquement il est faiblement typé. CLU, Standard ML et Haskell sont des exemples de langages vraiment fortement typés. Le standard ML a en fait subi plusieurs révisions pour supprimer les failles du système de type qui ont été découvertes après que le langage ait été largement déployé.

Que se passe-t-il vraiment ici?

Dans l'ensemble, il s'avère peu utile de parler de «fort» et de «faible». La question de savoir si un système de type a une échappatoire est moins importante que le nombre et la nature exacts des échappatoires, la probabilité qu'ils se présentent en pratique et les conséquences de l'exploitation d'une échappatoire. En pratique, il vaut mieux éviter les termes "fort" et "faible" , car

  • Les amateurs les confondent souvent avec "statique" et "dynamique".

  • Apparemment, le «typage faible» est utilisé par certaines personnes pour parler de la prévalence relative ou de l'absence de conversions implicites.

  • Les professionnels ne peuvent s'entendre sur la signification exacte des termes.

  • Dans l'ensemble, il est peu probable que vous informiez ou éclairiez votre public.

La triste vérité est que lorsqu'il s'agit de systèmes de types, «fort» et «faible» n'ont pas de signification technique universellement acceptée. Si vous voulez discuter de la force relative des systèmes de type, il est préférable de discuter exactement quelles garanties sont et ne sont pas fournies. Par exemple, une bonne question à poser est la suivante: "est-il garanti que chaque valeur d'un type (ou d'une classe) donnée a été créée en appelant l'un des constructeurs de ce type?" En C, la réponse est non. Dans CLU, F # et Haskell, c'est oui. Pour C ++, je ne suis pas sûr - je voudrais savoir.

En revanche, le typage statique signifie que les programmes sont vérifiés avant d'être exécutés et qu'un programme peut être rejeté avant son démarrage. Le typage dynamique signifie que les types de valeurs sont vérifiés pendant l' exécution et qu'une opération mal typée peut entraîner l'arrêt du programme ou signaler une erreur au moment de l'exécution. Une raison principale du typage statique est d'exclure les programmes qui pourraient avoir de telles "erreurs de type dynamique".

Est-ce que l'un implique l'autre?

Sur un plan pédant, non, car le mot «fort» ne veut vraiment rien dire. Mais dans la pratique, les gens font presque toujours l'une des deux choses suivantes:

  • Ils utilisent (à tort) «fort» et «faible» pour signifier «statique» et «dynamique», auquel cas ils utilisent (à tort) «fortement typé» et «statiquement typé» de manière interchangeable.

  • Ils utilisent «fort» et «faible» pour comparer les propriétés des systèmes de type statique. Il est très rare d'entendre quelqu'un parler d'un système de type dynamique "fort" ou "faible". À l'exception de FORTH, qui n'a pas vraiment de système de type, je ne peux pas penser à un langage typé dynamiquement où le système de type peut être subverti. Par définition, ces vérifications sont intégrées dans le moteur d'exécution et chaque opération est vérifiée avant d'être exécutée.

Quoi qu'il en soit, si une personne appelle une langue «fortement typée», cette personne parlera très probablement d'une langue typée statiquement.

Norman Ramsey
la source
3
@Adam: Evidemment pas assez correct pour être voté :) Parce que la réponse de Cletus contient tant d'idées fausses (bien que j'aie édité les pires d'entre elles), je me suis senti obligé de tout expliquer en mots d'une syllabe ...
Norman Ramsey
1
Eh bien, j'ai voté pour vous :) Même le mot «compiler» n'est pas clair avec les machines virtuelles actuelles exécutant des langages dynamiques. Techniquement, Java et C # sont tous deux compilés deux fois (JIT) et tous deux font une analyse de type. Un langage comme Javascript fonctionnant dans .NET vm pourrait être plus sécurisé à cause de la machine virtuelle.
Adam Gent
2
Je suis tellement confus maintenant! D'accord, chers grands gladiateurs de l'arène, une pauvre âme comme moi peut-elle accepter la simple compréhension suivante? Statique: les valeurs sont associées au type lors de la compilation et non lors de l'exécution pendant l'exécution. 3. Fort / faible: Oubliez ça! Ce ne sont pas des termes techniques et juste une mauvaise nomenclature. Cela dépend du contexte dont on parle. Puis-je continuer ma vie avec cette simple compréhension? :(
Saurabh Patil
"Est-ce que chaque valeur d'un type (ou classe) donné a été créée en appelant l'un des constructeurs de ce type?" En C, la réponse est non. Quelqu'un pourrait-il fournir un exemple de situation où cela se produit en C? Je suppose que cela implique de lancer des pointeurs sur des structures?
corazza
Typage fort et faible: aucune classification de ce type.
Raúl
248

C'est souvent mal compris alors permettez-moi de clarifier les choses.

Typage statique / dynamique

Le typage statique est l'endroit où le type est lié à la variable . Les types sont vérifiés au moment de la compilation.

La frappe dynamique est l'endroit où le type est lié à la valeur . Les types sont vérifiés au moment de l'exécution.

Donc en Java par exemple:

String s = "abcd";

ssera "pour toujours" un String. Au cours de sa vie, il peut pointer vers différents Strings (puisqu'il ss'agit d'une référence en Java). Il peut avoir une nullvaleur mais ne fera jamais référence à un Integerou à un List. C'est du typage statique.

En PHP:

$s = "abcd";          // $s is a string
$s = 123;             // $s is now an integer
$s = array(1, 2, 3);  // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class

C'est du typage dynamique.

Typage fort / faible

(Modifier l'alerte!)

La dactylographie forte est une phrase sans signification largement acceptée. La plupart des programmeurs qui utilisent ce terme pour signifier autre chose que le typage statique l'utilisent pour impliquer qu'il existe une discipline de type qui est appliquée par le compilateur. Par exemple, CLU a un système de type fort qui ne permet pas au code client de créer une valeur de type abstrait, sauf en utilisant les constructeurs fournis par le type. C a un système de type assez fort, mais il peut être "subverti" à un degré parce qu'un programme peut toujours convertir une valeur d'un type de pointeur en une valeur d'un autre type de pointeur. Ainsi, par exemple, en C, vous pouvez prendre une valeur renvoyée par malloc()et la convertir joyeusement enFILE* , et le compilateur n'essaiera pas de vous arrêter - ni même de vous avertir que vous faites quelque chose de louche.

(La réponse originale disait quelque chose à propos d'une valeur "ne changeant pas de type au moment de l'exécution". J'ai connu de nombreux concepteurs de langage et rédacteurs de compilateurs et je n'en connais aucun qui parlait de valeurs changeant de type au moment de l'exécution, sauf peut-être des recherches très avancées sur le type systèmes, où cela est connu comme le "problème de mise à jour forte".)

Un typage faible implique que le compilateur n'applique pas une discpline de typage, ou peut-être que l'application peut facilement être inversée.

L'original de cette réponse a confondu un typage faible avec une conversion implicite (parfois aussi appelée "promotion implicite"). Par exemple, en Java:

String s = "abc" + 123; // "abc123";

Ce code est un exemple de promotion implicite: 123 est implicitement converti en chaîne avant d'être concaténé avec "abc". On peut faire valoir que le compilateur Java réécrit ce code comme:

String s = "abc" + new Integer(123).toString();

Considérez un problème PHP «commence par» classique:

if (strpos('abcdef', 'abc') == false) {
  // not found
}

L'erreur ici est que strpos()renvoie l'index de la correspondance, étant 0. 0 est contraint en booléen falseet donc la condition est réellement vraie. La solution consiste à utiliser ===au lieu d' ==éviter la conversion implicite.

Cet exemple illustre comment une combinaison de conversion implicite et de typage dynamique peut égarer les programmeurs.

Comparez cela à Ruby:

val = "abc" + 123

ce qui est une erreur d'exécution car dans Ruby, l' objet 123 n'est pas implicitement converti simplement parce qu'il se trouve être passé à une +méthode. Dans Ruby, le programmeur doit rendre la conversion explicite:

val = "abc" + 123.to_s

La comparaison de PHP et Ruby en est une bonne illustration. Les deux sont des langages typés dynamiquement mais PHP a beaucoup de conversions implicites et Ruby (peut-être surprenant si vous ne le connaissez pas) ne le fait pas.

Statique / Dynamique vs Fort / Faible

Le point ici est que l'axe statique / dynamique est indépendant de l'axe fort / faible. Les gens les confondent probablement en partie parce que le typage fort vs faible n'est pas seulement moins clairement défini, il n'y a pas de véritable consensus sur ce que l'on entend exactement par fort et faible. Pour cette raison, la frappe forte / faible est beaucoup plus une nuance de gris plutôt que de noir ou de blanc.

Donc, pour répondre à votre question: une autre façon de voir cela qui est généralement correct est de dire que le typage statique est une sécurité de type à la compilation et un typage fort est une sécurité de type à l'exécution.

La raison en est que les variables dans un langage de type statique ont un type qui doit être déclaré et peut être vérifié au moment de la compilation. Un langage fortement typé a des valeurs qui ont un type au moment de l'exécution, et il est difficile pour le programmeur de renverser le système de type sans vérification dynamique.

Mais il est important de comprendre qu'un langage peut être statique / fort, statique / faible, dynamique / fort ou dynamique / faible.

cletus
la source
Au lieu de dire que $ s est un entier ou une chaîne, il aurait mieux valu que vous disiez que le type est associé à "abcd" ou 1234 pas à la variable $ s.
Srinivas Reddy Thatiparthy
Excellente réponse avec des exemples clairs. Cependant, je pense que cela ne résout pas complètement la confusion quant à la raison pour laquelle les gens posent des questions sur le fort / statique en tant que paire de concepts jumeaux. Par exemple, la formulation de l'OP de "est-ce que la frappe statique IMPLIQUE une frappe forte?" Votre réponse met l'accent sur leur indépendance. Pour continuer à clarifier pourquoi le fort est souvent associé à l'électricité statique, la réponse précédente de Norman Ramsey est très bonne: stackoverflow.com/questions/376611/…
JasDev
1
"abc" + 123est une erreur d' exécution , pas une erreur de compilation dans ruby. S'il s'agissait d'une erreur de compilation, ruby ​​serait typé statiquement.
sepp2k
Les exemples de dactylographie faible doivent être améliorés (voir ma réponse) mais sinon, le formatage est agréable.
Adam Gent
À mon avis, la typgin forte vs faible est la suivante: Strong: "c" + True = erreur d'exécution ou erreur de compilation. Faible: "c" + True = "b" ou "d" car tout est traité comme des octets bruts. Fort: C #, Ruby, C ++ Faible: Assembly, C (en raison de pointeurs vides implicites)
Jonathan Allen
17

Les deux sont des pôles sur deux axes différents:

  • fortement typé vs faiblement typé
  • typé statiquement vs dynamiquement typé

Fortement typé , un ne sera pas automatiquement converti d'un type à un autre. Faiblement tapé est le contraire: Perl peut utiliser une chaîne comme"123" dans un contexte numérique, en la convertissant automatiquement en int 123. Un langage fortement typé comme python ne le fera pas.

Typiquement , le compilateur détermine le type de chaque variable au moment de la compilation. Les langages typés dynamiquement ne déterminent les types de variables qu'au moment de l'exécution.

Daren Thomas
la source
6
Je dois être en désaccord. Un langage fortement typé est celui qui connaît les types au moment de l'exécution. Une langue faiblement typée est une langue qui n'aime pas l'assemblage. Votre exemple est sur un troisième axe, "conversions implicites vs explicites".
Jonathan Allen
1
En fait, je suis d'accord avec Jonathan, mais vous n'avez pas besoin d'avoir les types disponibles au moment de l'exécution pour être fortement typés si vous effectuez une analyse statique et n'autorisez pas la conversion. (voir ma réponse modifiée).
Adam Gent
1
Python est un exemple de langage typé dynamiquement et fortement typé
MaRoBet
13

Fortement typé signifie qu'il existe des restrictions entre les conversions entre les types. Le typage statique signifie que les types ne sont pas dynamiques - vous ne pouvez pas changer le type d'une variable une fois qu'elle a été créée.

Svetlozar Angelov
la source
Pour le démontrer: dans un langage fortement typé, vous ne pouvez pas comparer "5" == 5 et obtenir la vérité: les chaînes ne sont pas des entiers. Si ma mémoire est bonne, la plupart des langages de script modernes sont fortement typés dynamiquement. Tcl / Tk, cependant, est faiblement typé - Tout peut être traité comme une chaîne.
Little Bobby Tables
Bobby, dans un langage faiblement tapé "5" == 5 est lu comme 0x35 == 0x05. Ou en d'autres termes, tout est traité comme des octets bruts.
Jonathan Allen
Je dois être en désaccord avec vous deux. Prenez Lua; vous pouvez comparer "5" == 5 et cela retournera faux, cependant une conversion rapide peut être effectuée en allant "5" + 0.
RCIX
12

La contrainte de données ne signifie pas nécessairement faiblement typée car parfois son sucre syntaxique:

L'exemple ci-dessus de Java étant faiblement tapé à cause de

String s = "abc" + 123;

N'est pas un exemple faiblement typé car il fait vraiment:

String s = "abc" + new Integer(123).toString()

La coercition des données n'est pas non plus faiblement typée si vous construisez un nouvel objet. Java est un très mauvais exemple de type faiblement typé (et tout langage qui a une bonne réflexion ne sera probablement pas faiblement typé). Parce que le runtime du langage sait toujours quel est le type (l'exception peut être des types natifs).

C'est différent de C. C est l'un des meilleurs exemples de faiblement typé. Le runtime n'a aucune idée si 4 octets est un entier, une structure, un pointeur ou 4 caractères.

Le temps d'exécution du langage définit vraiment s'il est faiblement typé sinon son opinion est vraiment juste.

EDIT: Après mûre réflexion, ce n'est pas nécessairement vrai, car il n'est pas nécessaire que tous les types soient réifiés dans le système d'exécution pour être un système fortement typé. Haskell et ML disposent d'une analyse statique si complète qu'ils peuvent potentiellement ignorer les informations de type à l'exécution.

Adam Gent
la source
B est probablement un meilleur exemple, quoique un peu moins connu.
Tom Hawtin - tackline
Javascript est également assez faiblement typé mais parce qu'il y a si peu de types et parce que vous ne pouvez pas vraiment construire de nouveaux types.
Adam Gent
10

La réponse est déjà donnée ci-dessus. Essayer de faire la différence entre un concept fort vs semaine et un concept statique vs dynamique.

Qu'est-ce qui est fortement typé VS faiblement typé?

Fortement typé: ne sera pas automatiquement converti d'un type à un autre

Dans Go ou Python, comme les langages fortement typés, "2" + 8 soulèvera une erreur de type, car ils n'autorisent pas la "contrainte de type".

Faible (vaguement) typé: sera automatiquement converti en un type à un autre: les langages faiblement typés comme JavaScript ou Perl ne génèreront pas d'erreur et dans ce cas, JavaScript produira '28' et perl en produira 10.

Exemple Perl:

my $a = "2" + 8;
print $a,"\n";

Enregistrez-le sur main.pl et exécutez perl main.pl et vous obtiendrez la sortie 10.

Qu'est-ce que le type statique VS dynamique?

En programmation, le programmeur définit le typage statique et le typage dynamique par rapport au point auquel les types de variables sont vérifiés. Les langages typés statiques sont ceux dans lesquels la vérification de type est effectuée au moment de la compilation, tandis que les langages typés dynamiques sont ceux dans lesquels la vérification de type est effectuée au moment de l'exécution.

  • Statique: types vérifiés avant l'exécution
  • Dynamique: types vérifiés à la volée, lors de l'exécution

Qu'est-ce que cela signifie?

Dans Go, il vérifie tapé avant l'exécution (vérification statique). Cela signifie non seulement qu'il traduit et vérifie le code qu'il exécute, mais qu'il parcourra tout le code et que l'erreur de type serait levée avant même que le code ne soit exécuté. Par exemple,

package main

import "fmt"

func foo(a int) {
    if (a > 0) {
        fmt.Println("I am feeling lucky (maybe).")
    } else {
        fmt.Println("2" + 8)
    }
}

func main() {
    foo(2)
}

Enregistrez ce fichier dans main.go et exécutez-le, vous obtiendrez un message d'échec de compilation pour cela.

go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)

Mais ce cas n'est pas valable pour Python. Par exemple, le bloc de code suivant s'exécutera pour le premier appel foo (2) et échouera pour le deuxième appel foo (0). C'est parce que Python est typé dynamiquement, il ne traduit et ne vérifie que le code sur lequel il s'exécute. Le bloc else ne s'exécute jamais pour foo (2), donc "2" + 8 n'est même jamais regardé et pour foo (0), il essaiera d'exécuter ce bloc et échouera.

def foo(a):
    if a > 0:
        print 'I am feeling lucky.'
    else:
        print "2" + 8
foo(2)
foo(0)

Vous verrez la sortie suivante

python main.py
I am feeling lucky.
Traceback (most recent call last):
  File "pyth.py", line 7, in <module>
    foo(0)
  File "pyth.py", line 5, in foo
    print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects
Balkrishna
la source
8

L'un n'implique pas l'autre. Pour qu'un langage soit typé statiquement, cela signifie que les types de toutes les variables sont connus ou déduits au moment de la compilation.

Une langue fortement typée ne vous permet pas d'utiliser un type comme un autre. C est une langue faiblement typée et est un bon exemple de ce que les langues fortement typées ne permettent pas. En C, vous pouvez passer un élément de données du mauvais type et il ne se plaindra pas. Dans les langues fortement typées, vous ne pouvez pas.

Joe Cannatti
la source
7

Un typage fort signifie probablement que les variables ont un type bien défini et qu'il existe des règles strictes concernant la combinaison de variables de types différents dans les expressions. Par exemple, si A est un entier et B est un flottant, alors la règle stricte concernant A + B pourrait être que A est converti en un flottant et le résultat renvoyé comme un flottant. Si A est un entier et B est une chaîne, alors la règle stricte pourrait être que A + B n'est pas valide.

Le typage statique signifie probablement que les types sont assignés au moment de la compilation (ou son équivalent pour les langages non compilés) et ne peuvent pas changer pendant l'exécution du programme.

Notez que ces classifications ne s'excluent pas mutuellement, en effet je m'attendrais à ce qu'elles se produisent fréquemment ensemble. De nombreuses langues fortement typées sont également typées statiquement.

Et notez que lorsque j'utilise le mot «probablement», c'est parce qu'il n'y a pas de définitions universellement acceptées de ces termes. Comme vous l'avez déjà vu dans les réponses jusqu'à présent.

Marque de haute performance
la source