強い<=>弱い型付けは、あるデータ型から別のデータ型に言語によって自動的に強制される値の量の連続性に関するだけでなく、実際の値の強さまたは弱さ型付けのです。PythonとJava、そしてほとんどの場合C#では、値の型が明確になっています。Perlでは、それほど多くはありません-変数に格納できるのは、ほんの一握りの異なる値型だけです。
ケースを一つずつ開けましょう。
パイソン
Pythonの例では1 + "1"
、+
演算子は__add__
for型int
を呼び出し、文字列"1"
を引数として渡しますが、これによりNotImplementedが生成されます。
>>> (1).__add__('1')
NotImplemented
次に、インタプリタ__radd__
はstrを試します:
>>> '1'.__radd__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__radd__'
失敗すると、+
オペレーターは結果とともに失敗しTypeError: unsupported operand type(s) for +: 'int' and 'str'
ます。そのため、例外は強い型付けについてはあまり述べていませんが、演算子が強制しないという事実+
引数を自動的に同じ型にという事実は、Pythonが連続体で最も弱い型付けの言語ではないという事実へのポインタです。
一方、Python 'a' * 5
では実装されています。
>>> 'a' * 5
'aaaaa'
あれは、
>>> 'a'.__mul__(5)
'aaaaa'
演算が異なるという事実は、いくつかの強い型付けを必要とします-ただし、*
乗算する前に値を数値に強制変換することの反対は、必ずしも値の型付けを弱いとは限りません。
ジャワ
Javaの例は、String result = "1" + 1;
便宜上、演算子+
が文字列に対して多重定義されているためにのみ機能します。Java +
オペレーターは、シーケンスを次のものを作成するものに置き換えますStringBuilder
(これを参照):
String result = a + b;
// becomes something like
String result = new StringBuilder().append(a).append(b).toString()
これはむしろ静的な型付けの例であり、実際の強制StringBuilder
はありません- append(Object)
ここで特に使用されるメソッドがあります。ドキュメントには次のように書かれています:
Object
引数の文字列表現を追加します。
全体的な効果は、メソッドによって引数が文字列に変換され、String.valueOf(Object)
その文字列の文字がこの文字シーケンスに追加された場合とまったく同じです。
どこString.valueOf
に
Object引数の文字列表現を返します。[戻り値]引数がの場合null
、次に等しい文字列"null"
。それ以外の場合は、の値obj.toString()
が返されます。
したがって、これは言語による強制が絶対にないケースです-すべての懸念をオブジェクト自体に委任します。
C#
ここでのJon Skeetの回答によると、演算子+
はstring
クラスに対してオーバーロードされていません-Javaのように、これは静的型と強力型の両方のおかげで、コンパイラーによって生成された便利です。
Perl
以下のようperldataで説明し、
Perlには、スカラー、スカラーの配列、および「ハッシュ」と呼ばれるスカラーの連想配列の3つの組み込みデータ型があります。スカラーは、単一の文字列(任意のサイズ、使用可能なメモリによってのみ制限される)、数値、または何かへの参照(perlrefで説明されます)です。通常の配列は、0から始まる、番号でインデックス付けされたスカラーの順序付きリストです。ハッシュは、関連付けられた文字列キーでインデックス付けされたスカラー値の順序付けられていないコレクションです。
ただし、Perlには、数値、ブール値、文字列、null、undefined
s、他のオブジェクトへの参照などの個別のデータ型はありません。これらすべてに対して1つの型、スカラー型しかありません。0は "0"と同様にスカラー値です。文字列として設定されたスカラー変数は、実際には数値に変わる可能性があり、それ以降は「単なる文字列」とは異なる動作をします可能性があり、数値コンテキストでアクセスされる場合とはます。。スカラーはPerlで何でも保持できます。これは、システムに存在するオブジェクトと同じだけのオブジェクトです。Pythonでは名前はオブジェクトを参照するだけですが、Perlでは名前のスカラー値は変更可能なオブジェクトです。さらに、オブジェクト指向型システムはこの上に接着されています。perlには、スカラー、リスト、ハッシュの3つのデータ型しかありません。Perlのユーザー定義オブジェクトはbless
、パッケージへの参照(前の3つのいずれかへのポインター)です。このような値を取得して、いつでも任意のクラスに祝福できます。
Perlでは、気まぐれに値のクラスを変更することもできます。あるクラスの値を作成する場所では、そのクラスに属している値などを明示的に構築する必要があるPythonではこれは不可能object.__new__
です。Pythonでは、作成後にオブジェクトの本質を実際に変更することはできません。Perlでは、何でも行うことができます。
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";
したがって、タイプアイデンティティは変数に弱くバインドされており、その場で任意の参照を介して変更できます。実際には、
my $another = $val;
\$another
\$val
祝福された参照を提供しますが、クラスIDはありません。
TL; DR
Perlへの弱い型付けについては、自動強制よりもはるかに多く、動的でありながら非常に強く型付けされた言語であるPythonとは異なり、値自体の型は固定されていません。Pythonが与えるTypeError
こと1 + "1"
は、JavaまたはC#のように有用な何かをするという反対のことは強く型付けされた言語であることを排除しないにもかかわらず、言語が強く型付けされていることを示しています。