Bei der starken <=> schwachen Typisierung geht es nicht nur um das Kontinuum, wie viel oder wie wenig der Werte automatisch von der Sprache für einen Datentyp zu einem anderen gezwungen werden, sondern auch darum, wie stark oder schwach die tatsächlichen Werte typisiert werden. In Python und Java und hauptsächlich in C # sind die Typen der Werte in Stein gemeißelt. In Perl nicht so sehr - es gibt wirklich nur eine Handvoll verschiedener Werttypen, die in einer Variablen gespeichert werden können.
Lassen Sie uns die Fälle einzeln öffnen.
Python
In Python Beispiel 1 + "1"
, +
Operator ruft die __add__
für Typ int
die Zeichenfolge geben "1"
als Argument - aber diese Ergebnisse in NotImplemented:
>>> (1).__add__('1')
NotImplemented
Als nächstes versucht der Interpreter das __radd__
von str:
>>> '1'.__radd__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__radd__'
Wenn dies fehlschlägt, schlägt der +
Bediener mit dem Ergebnis fehl TypeError: unsupported operand type(s) for +: 'int' and 'str'
. Insofern sagt die Ausnahme nicht viel über starke Typisierung aus, aber die Tatsache, dass der Operator seine Argumente nicht automatisch auf denselben Typ +
zwingt , ist ein Hinweis darauf, dass Python nicht die am schwächsten typisierte Sprache im Kontinuum ist.
Auf der anderen Seite, in Python 'a' * 5
ist implementiert:
>>> 'a' * 5
'aaaaa'
Das ist,
>>> 'a'.__mul__(5)
'aaaaa'
Die Tatsache, dass die Operation anders ist, erfordert eine starke Typisierung - das Gegenteil *
davon, die Werte vor dem Multiplizieren zu Zahlen zu zwingen, würde die Werte jedoch nicht unbedingt schwach typisieren.
Java
Das Java-Beispiel String result = "1" + 1;
funktioniert nur, weil der Operator der Einfachheit +
halber für Zeichenfolgen überladen ist. Der Java- +
Operator ersetzt die Sequenz durch das Erstellen eines StringBuilder
(siehe hier ):
String result = a + b;
// becomes something like
String result = new StringBuilder().append(a).append(b).toString()
Dies ist eher ein Beispiel für eine sehr statische Typisierung ohne tatsächlichen Zwang - StringBuilder
hat eine Methode append(Object)
, die hier speziell verwendet wird. In der Dokumentation heißt es:
Hängt die Zeichenfolgendarstellung des Object
Arguments an.
Der Gesamteffekt ist genau so, als ob das Argument von der Methode in eine Zeichenfolge konvertiert würde String.valueOf(Object)
und die Zeichen dieser Zeichenfolge dann an diese Zeichenfolge angehängt würden.
Wo String.valueOf
dann ?
Gibt die Zeichenfolgendarstellung des Object-Arguments zurück. [Gibt zurück] Wenn das Argument lautet null
, ist eine Zeichenfolge gleich "null"
; Andernfalls wird der Wert von obj.toString()
zurückgegeben.
Dies ist also ein Fall, in dem die Sprache absolut keinen Zwang ausübt und jedes Anliegen an die Objekte selbst delegiert.
C #
Laut der Antwort von Jon Skeet ist der Operator +
für die string
Klasse nicht einmal überlastet - ähnlich wie bei Java. Dies ist nur die Bequemlichkeit, die der Compiler dank statischer und starker Typisierung generiert.
Perl
Wie die Perldata erklärt,
Perl verfügt über drei integrierte Datentypen: Skalare, Arrays von Skalaren und assoziative Arrays von Skalaren, die als "Hashes" bezeichnet werden. Ein Skalar ist eine einzelne Zeichenfolge (von beliebiger Größe, die nur durch den verfügbaren Speicher begrenzt ist), eine Zahl oder ein Verweis auf etwas (das in Perlref erläutert wird). Normale Arrays sind geordnete Listen von Skalaren, die nach Zahlen indiziert sind, beginnend mit 0. Hashes sind ungeordnete Sammlungen von Skalarwerten, die durch den zugehörigen Zeichenfolgenschlüssel indiziert werden.
Perl hat jedoch keinen separaten Datentyp für Zahlen, Boolesche Werte, Zeichenfolgen, Nullen, undefined
s, Verweise auf andere Objekte usw. - es gibt nur einen Typ für diese alle, den Skalartyp. 0 ist ein Skalarwert ebenso wie "0". Eine skalare Variable , die als Zeichenfolge festgelegt wurde, kann sich wirklich in eine Zahl ändern und sich von da an anders verhalten als "nur eine Zeichenfolge" wenn in einem numerischen Kontext darauf zugegriffen wird. Der Skalar kann alles in Perl enthalten, er ist genauso das Objekt wie es im System existiert. Während sich in Python die Namen nur auf die Objekte beziehen, sind in Perl die Skalarwerte in den Namen veränderbare Objekte. Darüber hinaus wird das objektorientierte Typsystem aufgeklebt: Perl-Skalare, Listen und Hashes enthalten nur 3 Datentypen.bless
zu einem Paket - Sie können jeden solchen Wert jederzeit für jede Klasse segnen.
Mit Perl können Sie sogar die Werteklassen nach Belieben ändern. Dies ist in Python nicht möglich. Wenn Sie einen Wert für eine Klasse erstellen möchten, müssen Sie den zu dieser Klasse gehörenden Wert explizit mit object.__new__
oder ähnlich konstruieren . In Python können Sie die Essenz des Objekts nach der Erstellung nicht wirklich ändern, in Perl können Sie vieles tun:
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";
Somit ist die Typidentität schwach an die Variable gebunden und kann durch jede Referenz im laufenden Betrieb geändert werden. In der Tat, wenn Sie dies tun
my $another = $val;
\$another
hat nicht die Klassenidentität, obwohl \$val
immer noch die gesegnete Referenz geben wird.
TL; DR
Schwaches Tippen in Perl ist viel mehr als nur automatisches Erzwingen, und es geht mehr darum, dass die Typen der Werte selbst nicht in Stein gemeißelt sind, im Gegensatz zu Python, das eine dynamisch und dennoch sehr stark typisierte Sprache ist. Das Python gibt TypeError
auf 1 + "1"
ist ein Hinweis darauf , dass die Sprache eingegeben wird , stark, obwohl das Gegenteil einer etwas Nützliches, wie in Java oder C # tut nicht ausschließen , sie stark typisierte Sprachen zu sein.