Güçlü <=> zayıf yazma sadece değerlerin bir veri tipinin dili tarafından otomatik olarak ne kadar veya ne kadar az otomatik olarak zorlandığı değil, aynı zamanda gerçek değerlerin ne kadar güçlü veya zayıf bir şekilde yazıldığıyla ilgili süreklilikle ilgilidir . Python ve Java'da ve çoğunlukla C #'da, değerlerin türleri taş olarak ayarlanır. Perl'de, çok fazla değil - bir değişkente depolamak için gerçekten sadece bir avuç farklı değer türü var.
Vakaları tek tek açalım.
piton
Python örneğinde 1 + "1"
, +
işleç , dizeyi bağımsız değişken olarak veren __add__
for türünü çağırır - ancak bu NotImplemented ile sonuçlanır:int
"1"
>>> (1).__add__('1')
NotImplemented
Ardından, tercüman str'yi dener __radd__
:
>>> '1'.__radd__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__radd__'
Başarısız olduğu için, +
operatör sonuçta başarısız olur TypeError: unsupported operand type(s) for +: 'int' and 'str'
. Bu nedenle, istisna güçlü yazım hakkında fazla bir şey söylemez, ancak operatörün argümanlarını otomatik olarak aynı türe +
zorlamaması , Python'un süreklilikteki en zayıf yazılan dil olmadığı gerçeğinin bir göstergesidir.
Öte yandan, Python 'a' * 5
edilir uygulanan:
>>> 'a' * 5
'aaaaa'
Yani,
>>> 'a'.__mul__(5)
'aaaaa'
İşlemin farklı olması, güçlü bir yazım gerektirir - ancak *
değerleri çarpmadan önce sayılara zorlamanın tersi , değerleri mutlaka zayıf yazmaz.
Java
Java örneği, String result = "1" + 1;
yalnızca kolaylık olması nedeniyle, işleç +
dizeler için aşırı yüklü olduğu için çalışır. Java +
operatör oluşturma dizisini değiştirir StringBuilder
(bakınız bu ):
String result = a + b;
// becomes something like
String result = new StringBuilder().append(a).append(b).toString()
Bu, gerçek bir baskı olmaksızın çok statik yazmanın bir örneğidir - burada özellikle kullanılan StringBuilder
bir yöntem append(Object)
vardır. Belgeler aşağıdakileri söylüyor:
Bağımsız Object
değişkenin dize olarak temsilini ekler .
Genel etki, tam olarak, argüman yöntemle bir dizeye dönüştürülmüş String.valueOf(Object)
ve bu dizenin karakterleri daha sonra bu karakter dizisine eklenmiştir.
Nerede String.valueOf
o zaman
Object bağımsız değişkeninin dize olarak temsilini döndürür. [Döndürür] argüman ise null
, o zaman "null"
; aksi takdirde değeri obj.toString()
döndürülür.
Bu nedenle, bu dil tarafından kesinlikle hiçbir zorlama yoktur - her kaygıyı nesnelerin kendisine devreder.
C #
Buradaki Jon Skeet cevabına göre , operatör sınıf +
için aşırı yüklenmiyor string
- Java'ya benzer, bu hem derleyici tarafından üretilen, hem statik hem de güçlü yazma sayesinde kolaylık.
Perl
Gibi perldata açıklıyor
Perl'in üç dahili veri türü vardır: skalerler, skaler dizileri ve "hash" olarak bilinen skalerlerin ilişkili dizileri. Skaler, tek bir dize (herhangi bir boyutta, yalnızca kullanılabilir bellekle sınırlıdır), sayı veya bir şeye referanstır (perlref'de tartışılacaktır). Normal diziler, 0 ile başlayarak sayı ile indekslenen skaler listeleridir. Karmalar, ilişkili dize anahtarıyla indekslenen skaler değerlerin sırasız koleksiyonlarıdır.
Bununla birlikte Perl, sayılar, booleans, dize, null, undefined
s, diğer nesnelere referanslar vb. İçin ayrı bir veri türüne sahip değildir - bu hepsi için tek bir türü vardır, skaler tip; 0, "0" kadar skaler bir değerdir. Dize olarak ayarlanmış bir skaler değişken gerçekten bir sayıya dönüşebilir ve sayısal bir bağlamda erişilirse oradan "sadece bir dize" den farklı şekilde davranabilir. Skaler Perl'de herhangi bir şeyi tutabilir, sistemde var olduğu kadar nesnedir. Python'da isimler sadece nesnelere atıfta bulunurken, Perl'de isimlerdeki skaler değerler değiştirilebilir nesnelerdir. Ayrıca, Nesneye Dayalı Tip sistemi bunun üzerine yapıştırılmıştır: perller, listeler ve karmalarda sadece 3 veri türü vardır. Perl'deki kullanıcı tanımlı bir nesne, bir referanstır (önceki 3'ten herhangi birine bir işaretçi)bless
Bir pakette düzenlenir - böyle bir değeri alabilir ve istediğiniz anda herhangi bir sınıfa kutlayabilirsiniz.
Perl bile kapıda değer sınıflarını değiştirmenize izin verir - bu, Python'da, o sınıfa ait object.__new__
veya benzer bir değeri açıkça oluşturmak için ihtiyacınız olan bazı sınıfların bir değerini oluşturmak için mümkün değildir . Python'da yaratılıştan sonra nesnenin özünü gerçekten değiştiremezsiniz, Perl'de çok şey yapabilirsiniz:
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";
bu nedenle tip kimliği değişkene zayıf bir şekilde bağlanır ve anında herhangi bir referansla değiştirilebilir. Aslında, eğer yaparsan
my $another = $val;
\$another
\$val
kutsanmış referansı vermesine rağmen, sınıf kimliğine sahip değildir .
TL; DR
Perl'e zayıf yazmayla ilgili otomatik zorlamalardan çok daha fazlası var ve dinamik olarak çok güçlü bir şekilde yazılmış bir dil olan Python'dan farklı olarak değerlerin türlerinin taşa yerleştirilmemesi daha fazla. Bu piton verir TypeError
üzerindeki 1 + "1"
Java veya C # gibi yararlı bir şey yapma aykırı bir, kesinlikle yazılı dilleri olmak onları engellemez rağmen, dil kesinlikle yazılı olduğu bir göstergesidir.