Yang kuat <=> lemah mengetik tidak hanya tentang kontinum pada seberapa banyak atau sedikit dari nilai-nilai yang dipaksa secara otomatis oleh bahasa untuk satu datatype yang lain, tetapi seberapa kuat atau lemah yang sebenarnya nilai-nilai yang diketik. Dalam Python dan Java, dan sebagian besar dalam C #, nilai-nilai memiliki tipe mereka diatur dalam batu. Dalam Perl, tidak begitu banyak - hanya ada beberapa set nilai yang berbeda untuk disimpan dalam variabel.
Mari kita buka kasing satu per satu.
Python
Dalam contoh Python 1 + "1"
, +
operator memanggil __add__
tipe untuk int
memberinya string "1"
sebagai argumen - namun, ini menghasilkan NotImplemented:
>>> (1).__add__('1')
NotImplemented
Selanjutnya, juru bahasa mencoba __radd__
str:
>>> '1'.__radd__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__radd__'
Karena gagal, +
operator gagal dengan hasilnya TypeError: unsupported operand type(s) for +: 'int' and 'str'
. Dengan demikian, perkecualian tidak mengatakan banyak tentang pengetikan yang kuat, tetapi fakta bahwa operator +
tidak memaksa argumennya secara otomatis ke tipe yang sama, adalah penunjuk fakta bahwa Python bukan bahasa yang diketik paling lemah dalam kontinum.
Di sisi lain, di Python 'a' * 5
adalah diimplementasikan:
>>> 'a' * 5
'aaaaa'
Itu adalah,
>>> 'a'.__mul__(5)
'aaaaa'
Fakta bahwa operasi berbeda memerlukan pengetikan yang kuat - namun kebalikan dari *
pemaksaan nilai ke angka sebelum dikalikan masih belum tentu membuat nilai diketik dengan lemah.
Jawa
Contoh Java, String result = "1" + 1;
hanya berfungsi karena sebagai fakta kenyamanan, operator +
kelebihan beban untuk string. +
Operator Java menggantikan urutan dengan menciptakan StringBuilder
(lihat ini ):
String result = a + b;
// becomes something like
String result = new StringBuilder().append(a).append(b).toString()
Ini lebih merupakan contoh pengetikan yang sangat statis, tanpa paksaan yang sebenarnya - StringBuilder
memiliki metode append(Object)
yang khusus digunakan di sini. Dokumentasi mengatakan sebagai berikut:
Menambahkan representasi string Object
argumen.
Efek keseluruhannya persis seperti argumen yang dikonversi ke string oleh metode String.valueOf(Object)
, dan karakter dari string itu kemudian ditambahkan ke urutan karakter ini.
String.valueOf
Lalu dimana
Mengembalikan representasi string dari argumen Object. [Kembali] jika argumennya adalah null
, maka sebuah string sama dengan "null"
; jika tidak, nilai obj.toString()
dikembalikan.
Jadi ini adalah kasus yang sama sekali tidak ada paksaan oleh bahasa - mendelegasikan setiap masalah ke objek itu sendiri.
C #
Menurut jawaban Jon Skeet di sini , operator +
bahkan tidak kelebihan beban untuk string
kelas - seperti Java, ini hanya kenyamanan yang dihasilkan oleh kompiler, berkat pengetikan yang statis dan kuat.
Perl
Seperti yang dijelaskan perldata ,
Perl memiliki tiga tipe data bawaan: skalar, array skalar, dan array asosiatif skalar, yang dikenal sebagai "hashes". Skalar adalah string tunggal (ukuran apa pun, hanya dibatasi oleh memori yang tersedia), angka, atau referensi ke sesuatu (yang akan dibahas dalam perlref). Array normal adalah daftar skalar yang diindeks berdasarkan angka, dimulai dengan 0. Hash adalah kumpulan nilai skalar yang tidak berurutan yang diindeks oleh kunci string yang terkait.
Namun Perl tidak memiliki tipe data terpisah untuk angka, boolean, string, nulls, undefined
s, referensi ke objek lain dll - ia hanya memiliki satu tipe untuk semua ini, tipe skalar; 0 adalah nilai skalar sebanyak "0". Variabel skalar yang ditetapkan sebagai string dapat benar-benar berubah menjadi angka, dan dari sana berperilaku berbeda dari "hanya string", jika diakses dalam konteks numerik. Skalar dapat menampung apa saja di Perl, objek sebanyak yang ada dalam sistem. sedangkan dalam Python nama hanya merujuk ke objek, di Perl nilai skalar dalam nama adalah objek yang dapat diubah. Lebih lanjut, sistem Object Oriented Type terpaku di atasnya: hanya ada 3 tipe data dalam perl - skalar, daftar dan hash. Objek yang ditetapkan pengguna dalam Perl adalah referensi (yang merupakan pointer ke salah satu dari 3 sebelumnya) yang bless
diedit ke sebuah paket - Anda dapat mengambil nilai seperti itu dan memberkatinya ke kelas mana saja kapan saja Anda inginkan.
Perl bahkan memungkinkan Anda untuk mengubah kelas nilai saat itu - ini tidak mungkin dalam Python di mana untuk membuat nilai beberapa kelas Anda perlu secara eksplisit membangun nilai milik kelas itu dengan object.__new__
atau serupa. Dengan Python Anda tidak dapat mengubah esensi objek setelah penciptaan, di Perl Anda dapat melakukan banyak hal:
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";
dengan demikian identitas tipe lemah terikat pada variabel, dan dapat diubah melalui referensi apa pun dengan cepat. Bahkan, jika Anda melakukannya
my $another = $val;
\$another
tidak memiliki identitas kelas, meskipun \$val
masih akan memberikan referensi yang diberkati.
TL; DR
Ada lebih banyak tentang pengetikan lemah ke Perl daripada hanya paksaan otomatis, dan lebih banyak tentang jenis nilai itu sendiri tidak ditetapkan menjadi batu, tidak seperti Python yang secara dinamis namun sangat diketik bahasa. Python memberi TypeError
pada 1 + "1"
merupakan indikasi bahwa bahasa tersebut sangat diketik, meskipun sebaliknya melakukan sesuatu yang bermanfaat, seperti di Jawa atau C # tidak menghalangi mereka menjadi bahasa yang diketik dengan kuat.