แข็งแรง <=> พิมพ์อ่อนแอไม่เพียงเกี่ยวกับความต่อเนื่องเกี่ยวกับวิธีการมากหรือน้อยของค่าที่มีการข่มขู่โดยอัตโนมัติจากภาษาหนึ่งไปยังอีกประเภทข้อมูล แต่วิธีการขอหรืออ่อนที่เกิดขึ้นจริงค่าพิมพ์ ใน Python และ Java และส่วนใหญ่เป็น C # ค่าจะมีประเภทเป็นหิน ใน Perl ไม่มาก - มีเพียงไม่กี่แบบในการจัดเก็บในตัวแปร
เรามาเปิดเคสกันทีละตัว
หลาม
ในหลามตัวอย่าง1 + "1"
, +
ผู้ประกอบการเรียก__add__
สำหรับประเภท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 [Returns] ถ้าอาร์กิวเมนต์เป็นnull
แล้วสตริงเท่ากับ"null"
; มิฉะนั้นobj.toString()
จะส่งคืนค่าของ
ดังนั้นนี่เป็นกรณีที่ไม่มีการบีบบังคับโดยภาษาอย่างแท้จริง - มอบทุกสิ่งที่เกี่ยวข้องกับวัตถุเอง
ค#
ตามคำตอบของJon Skeet ที่นี่ผู้ประกอบการ+
ไม่ได้รับภาระมากเกินไปสำหรับstring
คลาส - ซึ่งคล้ายกับ Java นี่เป็นเพียงความสะดวกสบายที่สร้างโดยคอมไพเลอร์ด้วยการพิมพ์ทั้งแบบคงที่และแรง
Perl
ตามที่perldataอธิบาย
Perl มีข้อมูลในตัวสามประเภท: สเกลาร์, สเกลาร์ของสเกลาร์, และอาเรย์ที่เชื่อมโยงของสเกลาร์, รู้จักกันในนาม "แฮช" เซนต์คิตส์และเนวิสเป็นสเกลเดี่ยว (ทุกขนาด จำกัด เฉพาะหน่วยความจำที่มีอยู่) จำนวนหรือการอ้างอิงถึงบางสิ่ง (ซึ่งจะกล่าวถึงใน perlref) อาร์เรย์ปกติจะเรียงลำดับรายการสเกลาร์ที่จัดทำดัชนีตามหมายเลขโดยเริ่มต้นด้วย 0 แฮชคือชุดสะสมของค่าสเกลาร์ที่ไม่ได้เรียงลำดับดัชนีโดยสตริงสตริงที่เกี่ยวข้อง
Perl แต่ไม่มีประเภทข้อมูลแยกต่างหากสำหรับตัวเลข, booleans, สตริง, nulls, undefined
s, การอ้างอิงไปยังวัตถุอื่น ๆ ฯลฯ - มันมีเพียงประเภทเดียวสำหรับสิ่งเหล่านี้ทั้งหมด, ประเภทสเกลาร์; 0 คือค่าสเกลาร์มากเท่ากับ "0" ตัวแปรสเกลาร์ที่ถูกตั้งค่าเป็นสตริงสามารถเปลี่ยนเป็นตัวเลขได้จริงและจากที่นั่นจะทำงานแตกต่างจาก "เพียงแค่สตริง" หากมีการเข้าถึงในบริบทตัวเลข. เซนต์คิตส์และเนวิสสามารถเก็บอะไรก็ได้ใน Perl มันเป็นวัตถุที่มีอยู่ในระบบ ในขณะที่ใน Python ชื่อเพียงหมายถึงวัตถุใน Perl ค่าสเกลาร์ในชื่อเป็นวัตถุที่เปลี่ยนแปลงได้ นอกจากนี้ระบบ Object Oriented Type ยังติดอยู่ด้านบนของสิ่งนี้: มีเพียง 3 ประเภทข้อมูลใน perl - scalars, รายการและแฮช วัตถุที่ผู้ใช้กำหนดใน Perl เป็นการอ้างอิง (นั่นคือตัวชี้ไปยัง 3 จากก่อนหน้านี้) bless
ไปยังแพ็คเกจ - คุณสามารถนำค่าดังกล่าวมาใช้และอวยพรให้กับคลาสใด ๆ ในทันทีที่คุณต้องการ
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
จะยังคงให้การอ้างอิงที่มีความสุข
TL; DR
มีมากขึ้นเกี่ยวกับการพิมพ์ที่อ่อนแอไปยัง Perl มากกว่าการข่มขู่โดยอัตโนมัติและมันเป็นมากกว่าเกี่ยวกับประเภทของค่าที่ตัวเองไม่ได้กำหนดไว้ในหินซึ่งแตกต่างจาก Python ซึ่งเป็นภาษาแบบไดนามิกยังพิมพ์อย่างรุนแรงมาก งูหลามที่ให้TypeError
ใน1 + "1"
ข้อบ่งชี้ว่าภาษาที่มีการพิมพ์ขอแม้ว่าหนึ่งในทางตรงกันข้ามในการทำสิ่งที่มีประโยชน์เช่นเดียวกับใน Java หรือ C # ไม่ได้ดักคอพวกเขาเป็นภาษาพิมพ์มั่น