Le typage fort <=> faible ne concerne pas seulement le continuum sur la quantité ou le peu de valeurs qui sont automatiquement forcées par la langue pour un type de données à un autre, mais la force ou la faiblesse des valeurs réelles typées. En Python et Java, et principalement en C #, les valeurs ont leurs types gravés dans la pierre. En Perl, pas tellement - il n'y a vraiment qu'une poignée de types de valeurs différents à stocker dans une variable.
Ouvrons les cas un par un.
Python
Dans l'exemple Python 1 + "1"
, l' +
opérateur appelle le __add__
type for int
en lui donnant la chaîne "1"
comme argument - cependant, cela se traduit par NotImplemented:
>>> (1).__add__('1')
NotImplemented
Ensuite, l'interpréteur essaie le __radd__
of str:
>>> '1'.__radd__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__radd__'
Lorsqu'il échoue, l' +
opérateur échoue avec le résultat TypeError: unsupported operand type(s) for +: 'int' and 'str'
. En tant que telle, l'exception ne dit pas grand-chose sur le typage fort, mais le fait que l'opérateur +
ne contraint pas automatiquement ses arguments au même type, est un indicateur sur le fait que Python n'est pas le langage le plus faiblement typé du continuum.
D'autre part, en Python 'a' * 5
est implémenté:
>>> 'a' * 5
'aaaaa'
C'est,
>>> 'a'.__mul__(5)
'aaaaa'
Le fait que l'opération soit différente nécessite un typage fort - cependant le contraire de *
forcer les valeurs à des nombres avant de multiplier encore ne rendrait pas nécessairement les valeurs faiblement typées.
Java
L'exemple Java String result = "1" + 1;
ne fonctionne que parce que par commodité, l'opérateur +
est surchargé pour les chaînes. L' +
opérateur Java remplace la séquence par la création d'un StringBuilder
(voir ceci ):
String result = a + b;
// becomes something like
String result = new StringBuilder().append(a).append(b).toString()
Ceci est plutôt un exemple de typage très statique, sans aucune contrainte réelle - StringBuilder
a une méthode append(Object)
qui est spécifiquement utilisée ici. La documentation dit ce qui suit:
Ajoute la représentation sous forme de chaîne de l' Object
argument.
L'effet global est exactement comme si l'argument était converti en chaîne par la méthode String.valueOf(Object)
, et les caractères de cette chaîne étaient ensuite ajoutés à cette séquence de caractères.
Où String.valueOf
alors
Renvoie la représentation sous forme de chaîne de l'argument Object. [Renvoie] si l'argument est null
, alors une chaîne égale à "null"
; sinon, la valeur de obj.toString()
est renvoyée.
Il s'agit donc d'un cas d'absolument aucune contrainte de la part du langage - déléguant toute préoccupation aux objets eux-mêmes.
C #
Selon la réponse de Jon Skeet ici , l'opérateur +
n'est même pas surchargé pour la string
classe - à l'instar de Java, ce n'est que la commodité générée par le compilateur, grâce à la fois à un typage statique et fort.
Perl
Comme l' explique la perldata ,
Perl a trois types de données intégrés: les scalaires, les tableaux de scalaires et les tableaux associatifs de scalaires, appelés «hachages». Un scalaire est une chaîne unique (de n'importe quelle taille, limitée uniquement par la mémoire disponible), un nombre ou une référence à quelque chose (qui sera discuté dans perlref). Les tableaux normaux sont des listes ordonnées de scalaires indexées par nombre, commençant par 0. Les hachages sont des collections non ordonnées de valeurs scalaires indexées par leur clé de chaîne associée.
Cependant, Perl n'a pas de type de données séparé pour les nombres, les booléens, les chaînes, les valeurs nulles, les undefined
s, les références à d'autres objets, etc. - il n'a qu'un seul type pour tous, le type scalaire; 0 est une valeur scalaire autant que "0". Une variable scalaire qui a été définie comme une chaîne peut vraiment se transformer en nombre, et à partir de là, se comporter différemment de "juste une chaîne", si elle est accédée dans un contexte numérique. Le scalaire peut contenir n'importe quoi en Perl, c'est autant l'objet qu'il existe dans le système. alors qu'en Python les noms font simplement référence aux objets, en Perl les valeurs scalaires dans les noms sont des objets modifiables. De plus, le système de type orienté objet est collé dessus: il n'y a que 3 types de données dans perl - scalaires, listes et hachages. Un objet défini par l'utilisateur en Perl est une référence (c'est-à-dire un pointeur vers l'une des 3 précédentes) bless
éditée vers un paquet - vous pouvez prendre une telle valeur et la donner à n'importe quelle classe à tout moment.
Perl vous permet même de changer les classes de valeurs à volonté - ce n'est pas possible en Python où pour créer une valeur d'une classe, vous devez explicitement construire la valeur appartenant à cette classe avec object.__new__
ou similaire. En Python, vous ne pouvez pas vraiment changer l'essence de l'objet après la création, en Perl vous pouvez faire beaucoup de choses:
package Foo;
package Bar;
my $val = 42;
# $val is now a scalar value set from double
bless \$val, Foo;
# all references to $val now belong to class Foo
my $obj = \$val;
# now $obj refers to the SV stored in $val
# thus this prints: Foo=SCALAR(0x1c7d8c8)
print \$val, "\n";
# all references to $val now belong to class Bar
bless \$val, Bar;
# thus this prints Bar=SCALAR(0x1c7d8c8)
print \$val, "\n";
# we change the value stored in $val from number to a string
$val = 'abc';
# yet still the SV is blessed: Bar=SCALAR(0x1c7d8c8)
print \$val, "\n";
# and on the course, the $obj now refers to a "Bar" even though
# at the time of copying it did refer to a "Foo".
print $obj, "\n";
ainsi l'identité de type est faiblement liée à la variable, et elle peut être modifiée par n'importe quelle référence à la volée. En fait, si vous faites
my $another = $val;
\$another
n'a pas l'identité de classe, même s'il \$val
donnera toujours la référence bénie.
TL; DR
Il y a beaucoup plus à propos du typage faible en Perl que de simples coercitions automatiques, et il s'agit davantage du fait que les types de valeurs eux-mêmes ne sont pas gravés dans la pierre, contrairement au Python qui est un langage dynamiquement mais très fortement typé. Ce python donne TypeError
sur 1 + "1"
est une indication que la langue est fortement typé, même si celui contraire de faire quelque chose d' utile, comme en Java ou C # ne les empêche pas d' être un langage fortement typé.