ความแตกต่างระหว่างภาษาที่พิมพ์แบบคงที่และภาษาที่พิมพ์แบบไดนามิกคืออะไร?


945

ฉันได้ยินมาว่าภาษาการเขียนโปรแกรมใหม่นั้นถูกพิมพ์แบบไดนามิก แต่จริงๆแล้วมันหมายความว่าอย่างไรเมื่อเราพูดว่าภาษานั้นถูกพิมพ์แบบไดนามิกและแบบคงที่?


25
เป็นคำถามที่ดี แต่คำตอบที่คุณยอมรับไม่ใช่คำตอบที่ถูกต้อง
Jon Harrop

42
คุณช่วยแนะนำสิ่งที่ถูกต้องได้ไหม?
Sagiruddin Mondal

@EricLeschinski ฉันคิดว่าการทดสอบหน่วยช่วยด้วยปัญหาและภาษาที่พิมพ์แบบไดนามิกเช่นJavaScriptสามารถเขียนด้วยความมั่นใจว่ามันจะถือขึ้นจึงทำให้มันมีคุณสมบัติเหมาะสมสำหรับการพัฒนาซอฟต์แวร์ขององค์กรคุณจะไม่คิดว่า?
พิกเซล 67

8
ที่ดีที่สุดการทดสอบหน่วยเหล่านั้นลดลงตามเวลาและถูกปิดโดยเพื่อนร่วมงานพยายามที่จะเพิ่มความปลอดภัยของงานที่เลวร้ายที่สุดพวกเขาไม่เคยเขียนในตอนแรก มันก็เหมือนกับการแนะนำให้ช่างมืออาชีพใช้เทปพันท่อบนรถยนต์ของลูกค้า ใช่รุ่นน้องใช้เทปพันสายในงานส่งนี้เป็นความคิดที่ดี ... สำหรับคุณ
Eric Leschinski

2
ฉันรู้ว่าคำถามนี้มีอายุ 10 ปี แต่จากสิ่งที่ฉันอ่านในความคิดเห็นคุณควรเปลี่ยนเพื่อยอมรับคำตอบจาก "Christopher Tokar"
Rev1.0

คำตอบ:


853

ภาษาที่พิมพ์แบบคงที่

ภาษาจะถูกพิมพ์แบบคงที่หากทราบชนิดของตัวแปร ณ เวลารวบรวม สำหรับบางภาษานี่หมายความว่าคุณในฐานะโปรแกรมเมอร์ต้องระบุชนิดของตัวแปรแต่ละตัว (เช่น: Java, C, C ++); ภาษาอื่นเสนอรูปแบบการอนุมานบางประเภทความสามารถของระบบประเภทเพื่ออนุมานประเภทของตัวแปร (เช่น: OCaml, Haskell, Scala, Kotlin)

ข้อได้เปรียบหลักที่นี่คือการตรวจสอบทุกชนิดสามารถทำได้โดยคอมไพเลอร์และดังนั้นจึงมีข้อผิดพลาดเล็กน้อยที่เกิดขึ้นในระยะแรก

ตัวอย่าง: C, C ++, Java, Rust, Go, Scala

ภาษาที่พิมพ์แบบไดนามิก

ภาษาจะถูกพิมพ์แบบไดนามิกหากประเภทที่เกี่ยวข้องกับค่าทำงานและไม่ได้ตั้งชื่อตัวแปร / เขต / ฯลฯ ซึ่งหมายความว่าคุณในฐานะโปรแกรมเมอร์สามารถเขียนได้เร็วขึ้นเล็กน้อยเนื่องจากคุณไม่จำเป็นต้องระบุชนิดทุกครั้ง (ยกเว้นกรณีที่ใช้ภาษาที่พิมพ์แบบคงที่ด้วยการอนุมานประเภท )

ตัวอย่าง: Perl, Ruby, Python, PHP, JavaScript

ภาษาสคริปต์ส่วนใหญ่มีคุณสมบัตินี้เนื่องจากไม่มีคอมไพเลอร์ที่จะทำการตรวจสอบชนิดคงที่ แต่คุณอาจพบว่าตัวเองกำลังค้นหาข้อผิดพลาดที่เกิดจากล่ามตีความผิดประเภทของตัวแปร โชคดีที่สคริปต์มีแนวโน้มที่จะเล็กดังนั้นบั๊กจึงไม่มีที่ซ่อนมากมาย

ภาษาที่พิมพ์แบบไดนามิกส่วนใหญ่อนุญาตให้คุณให้ข้อมูลประเภท แต่ไม่จำเป็นต้องใช้ ภาษาหนึ่งที่ได้รับการพัฒนาในปัจจุบันคือRascalใช้วิธีไฮบริดที่ช่วยให้การพิมพ์แบบไดนามิกภายในฟังก์ชั่น แต่บังคับให้พิมพ์แบบคงที่สำหรับลายเซ็นฟังก์ชั่น


6
@NomeN คุณสามารถตั้งชื่อภาษาที่พิมพ์แบบไดนามิกใด ๆ ที่ใช้การอนุมาน HM ชนิดได้หรือไม่?
Pete Kirkham

88
"ภาษาจะถูกพิมพ์แบบไดนามิกหากชนิดของตัวแปรถูกตีความที่รันไทม์": ไม่ภาษาจะถูกพิมพ์แบบไดนามิกหากประเภทนั้นเกี่ยวข้องกับค่าเวลาทำงานและไม่ได้ตั้งชื่อตัวแปร / เขต / ฯลฯ
Paul Biggar

15
ไม่ถูกต้องการพิมพ์แบบสแตติกหมายถึง "ที่ค่าอ้างอิงนั้นประจักษ์ (ซึ่งไม่เหมือนกับเวลารวบรวม) ที่ถูก จำกัด ด้วยความเคารพต่อชนิดของค่าที่สามารถแสดงได้และการใช้ภาษาไม่ว่าจะเป็นคอมไพเลอร์หรือล่าม ทั้งบังคับใช้และใช้ข้อ จำกัด เหล่านี้ให้มากที่สุด " อ้างจาก: c2.com/cgi/wiki?StaticTypingสิ่งที่ฉันเข้าใจได้ถูกต้อง
Matthias Wolf

6
สิ่งที่ชัดเจนที่สุดเกี่ยวกับระบบประเภทของ Java, C, C ++, Pascal และภาษา“ อุตสาหกรรม” ที่ใช้กันอย่างแพร่หลายอื่น ๆ ไม่ใช่ว่าพวกเขาจะพิมพ์แบบคงที่ แต่พวกเขาจะพิมพ์อย่างชัดเจนในคำอื่น ๆ พวกเขาต้องการจำนวนมาก ประกาศประเภท (ในโลกของภาษาที่พิมพ์น้อยลงอย่างชัดเจนซึ่งการประกาศเหล่านี้เป็นทางเลือกมักจะเรียกว่า "คำอธิบายประกอบประเภท") สิ่งนี้ไม่มีส่วนเกี่ยวข้องกับประเภทคงที่ ดำเนินการต่อ ..
Vipresh

7
ภาษาที่พิมพ์แบบสแตติกแรกถูกพิมพ์โดยความจำเป็นอย่างชัดเจน อย่างไรก็ตามอัลกอริธึมการอนุมานแบบพิมพ์ - เทคนิคสำหรับการดูซอร์สโค้ดโดยไม่มีการประกาศชนิดเลยและตัดสินใจว่าตัวแปรชนิดใดที่มีอยู่มาหลายปีแล้ว ภาษา ML ซึ่งใช้งาน Haskell ซึ่งปรับปรุงให้ดีขึ้นนั้นมีอายุประมาณ 15 ปี แม้แต่ตอนนี้ C # ก็ยอมรับความคิดนี้ซึ่งจะทำให้เกิดคิ้วจำนวนมากและไม่ต้องสงสัยเลยว่าการอ้างว่ามันเป็น ดำเนินการต่อ ...
Vipresh

399

ภาษาการเขียนโปรแกรมแบบคงที่จะทำการตรวจสอบประเภท (เช่นกระบวนการตรวจสอบและบังคับใช้ข้อ จำกัด ของประเภท) ในเวลารวบรวมเมื่อเทียบกับเวลาทำงาน

พิมพ์แบบไดนามิกภาษาโปรแกรมทำการตรวจสอบชนิดที่เวลาทำงานเมื่อเทียบกับเวลารวบรวม

ตัวอย่างของภาษาที่พิมพ์แบบคงที่คือ: - Java, C, C ++

ตัวอย่างของภาษาที่พิมพ์แบบไดนามิก ได้แก่ - Perl, Ruby, Python, PHP, JavaScript


19
ฉันคิดว่านี่เป็นคำตอบที่ดีที่สุด โดยเฉพาะคำตอบที่ได้รับการยอมรับนั้นไม่ถูกต้องตามข้อเท็จจริง
Jon Harrop

1
@ JonHarrop มีวิธีการเฉพาะในด้านใดบ้าง?
1252748

21
@ โทมัส: "ซึ่งหมายความว่าคุณในฐานะโปรแกรมเมอร์สามารถเขียนเร็วขึ้นเล็กน้อยเพราะคุณไม่ต้องระบุประเภททุกครั้ง" คุณไม่จำเป็นต้องระบุชนิดทุกครั้งด้วยการพิมพ์แบบสแตติกถ้าคุณมีการอนุมานประเภท ดู SML, OCaml, F #, Haskell ...
Jon Harrop

1
ในภาษา prog ที่พิมพ์แบบสแตติกการตรวจสอบชนิดจะทำก่อนรันไทม์ แต่ไม่ใช่ในเวลารวบรวม
Luiz Felipe

307

นี่คือตัวอย่างที่ตัดกันวิธีที่ Python (พิมพ์แบบไดนามิก) และ Go (พิมพ์แบบคงที่) จัดการข้อผิดพลาดประเภท:

def silly(a):
    if a > 0:
        print 'Hi'
    else:
        print 5 + '3'

Python ทำการพิมพ์การตรวจสอบ ณ รันไทม์และดังนั้น:

silly(2)

Hiทำงานสมบูรณ์ดีและผลิตออกที่คาดว่าจะ เกิดข้อผิดพลาดก็ต่อเมื่อมีการตีบรรทัดที่มีปัญหา:

silly(-1)

ผลิต

TypeError: unsupported operand type(s) for +: 'int' and 'str'

เพราะบรรทัดที่เกี่ยวข้องถูกดำเนินการจริง

ในอีกทางหนึ่งจะทำการตรวจสอบชนิดที่รวบรวมเวลา:

package main

import ("fmt"
)

func silly(a int) {
    if (a > 0) {
        fmt.Println("Hi")
    } else {
        fmt.Println("3" + 5)
    }
}

func main() {
    silly(2)
}

ข้างต้นจะไม่รวบรวมมีข้อผิดพลาดดังต่อไปนี้:

invalid operation: "3" + 5 (mismatched types string and int)

5
ขอบคุณสำหรับตัวอย่างที่เป็นระเบียบ ดังนั้นฉันจึงอนุมานว่าภาษาสคริปต์ทั้งหมดมีการพิมพ์แบบไดนามิกเนื่องจากพวกเขาไม่ได้รวบรวม?
CᴴᴀZ

8
ใช่. ภาษาสคริปต์ทั้งหมดจะถูกพิมพ์แบบไดนามิกเพราะพวกเขาไม่มีคอมไพเลอร์ที่จะทำการตรวจสอบประเภทคงที่ต่อไป จุดนี้ได้รับการแสดงในบทความนี้sitepoint.com/typing-versus-dynamic-typing
Shashi

9
Scala สามารถใช้เป็นภาษาสคริปต์และมันถูกพิมพ์แบบคงที่! #discussion @Shashi
Sagiruddin Mondal

3
@Shashi Compilation ไม่ได้แปลว่าเป็นแบบคงที่ Haskell สามารถตีความได้runhaskellเช่น
BalinKingOfMoria Reinstate CMs

2
ด้วยภาษาสคริปต์ไม่ได้แปลความหมายของภาษา TypeScript ถูกพิมพ์แบบคงที่รวบรวม / transpiled แต่ภาษาสคริปต์
metalim

161

เพียงวางไว้ในลักษณะนี้: ในประเภทของตัวแปรภาษาที่พิมพ์แบบสแตติกจะเป็นแบบสแตติกหมายถึงเมื่อคุณตั้งค่าตัวแปรให้เป็นประเภทคุณจะไม่สามารถเปลี่ยนได้ นั่นเป็นเพราะการพิมพ์เกี่ยวข้องกับตัวแปรมากกว่าค่าที่มันอ้างถึง

ตัวอย่างเช่นใน Java:

String str = "Hello";  //variable str statically typed as string
str = 5;               //would throw an error since str is supposed to be a string only

ในทางกลับกัน: ในประเภทตัวแปรภาษาที่พิมพ์แบบไดนามิกนั้นเป็นแบบไดนามิกหมายถึงหลังจากที่คุณตั้งค่าตัวแปรให้เป็นประเภทคุณสามารถเปลี่ยนได้ นั่นเป็นเพราะการพิมพ์มีความเกี่ยวข้องกับค่าที่มันคิดมากกว่าตัวแปร

ตัวอย่างเช่นใน Python:

str = "Hello" # variable str is linked to a string value
str = 5       # now it is linked to an integer value; perfectly OK

ดังนั้นควรคิดถึงตัวแปรในภาษาที่พิมพ์แบบไดนามิกเป็นเพียงพอยน์เตอร์ทั่วไปกับค่าที่พิมพ์

หากต้องการสรุปให้พิมพ์อธิบาย (หรือควรอธิบาย) ตัวแปรในภาษามากกว่าภาษานั้น ๆ มันน่าจะถูกใช้เป็นภาษาที่มีตัวแปรที่พิมพ์แบบคงที่และภาษาที่มีตัวแปรที่พิมพ์แบบไดนามิก IMHO

ภาษาที่พิมพ์แบบคงที่มักเป็นภาษาที่คอมไพล์ดังนั้นคอมไพเลอร์จะตรวจสอบประเภท (ทำให้เข้าใจได้อย่างสมบูรณ์แบบเนื่องจากไม่อนุญาตให้เปลี่ยนประเภทในภายหลังในเวลาทำงาน)

โดยทั่วไปแล้วภาษาที่พิมพ์แบบไดนามิกจะถูกตีความดังนั้นการตรวจสอบประเภท (ถ้ามี) เกิดขึ้นในเวลาทำงานเมื่อมีการใช้งาน หลักสูตรนี้นำค่าใช้จ่ายประสิทธิภาพมาใช้และเป็นหนึ่งในเหตุผลที่ภาษาไดนามิก (เช่น python, ruby, php) ไม่ได้ปรับขนาดได้ดีเท่ากับภาษาที่พิมพ์ (java, c #, ฯลฯ ) จากมุมมองอื่นภาษาที่พิมพ์แบบคงที่มีค่าใช้จ่ายในการเริ่มต้นมากขึ้น: ทำให้คุณเขียนโค้ดเพิ่มเติมได้ยากขึ้น แต่นั่นจ่ายในภายหลัง

สิ่งที่ดีคือทั้งสองด้านกำลังยืมคุณสมบัติจากอีกด้านหนึ่ง ภาษาที่พิมพ์จะรวมคุณสมบัติแบบไดนามิกมากขึ้นเช่น generics และไลบรารีแบบไดนามิกใน c # และภาษาแบบไดนามิกรวมถึงการตรวจสอบประเภทอื่น ๆ เช่นคำอธิบายประกอบประเภทใน python หรือตัวแปร HACK ของ PHP ซึ่งโดยทั่วไปจะไม่สำคัญกับภาษาและสามารถใช้งานได้ ความต้องการ

เมื่อพูดถึงการเลือกเทคโนโลยีไม่มีด้านใดมีความเหนือกว่าที่แท้จริงในอีกด้านหนึ่ง เป็นเรื่องของการตั้งค่าไม่ว่าคุณต้องการควบคุมเพิ่มเติมเพื่อเริ่มต้นด้วยหรือความยืดหยุ่น เพียงเลือกเครื่องมือที่เหมาะสมสำหรับงานและตรวจสอบให้แน่ใจว่าได้ตรวจสอบสิ่งที่มีอยู่ในด้านตรงข้ามก่อนพิจารณาสวิตช์


8
มันสมเหตุสมผลมาก ฉันคิดว่ามันอธิบายอย่างน้อยที่สุดเหตุผลที่อยู่เบื้องหลังชื่อดีกว่าคำตอบอื่น ๆ ที่นี่
JamEngulfer

อ้างอิงจากเอกสารอ้างอิงนี้ Python เป็นทั้งภาษาที่พิมพ์และพิมพ์แบบไดนามิก: wiki.python.org/moin/…ไม่มีใครรู้ว่าทำไม?
modulitos

1
ลูคัสในทางตรงข้ามกับเอกสารที่ย้ำให้เห็นว่างูใหญ่เป็นทั้งแรงและพิมพ์แบบไดนามิก คุณเห็นที่ไหน คุณพูดได้ไหม
mehmet

2
ฉันคิดว่าคำตอบนี้จะสื่อสารแนวคิดในแบบที่ง่ายที่สุด คำตอบอื่น ๆ มากมายพยายามอธิบายแนวคิดที่เป็นนามธรรม แต่ล้มเหลวในรายละเอียดบางอย่าง ฉันอยากเห็นคำตอบนี้ที่ด้านบนของรายการ
Hawkeye

5
คำตอบอื่น ๆ ส่วนใหญ่สร้างคำถามเพิ่มเติมในใจของฉัน อันนี้เคลียร์ทั้งหมด คำตอบนี้ควรจะอยู่ที่ด้านบนของ IMHO
Hami Torun

39

http://en.wikipedia.org/wiki/Type_system

การพิมพ์แบบคงที่

ภาษาการเขียนโปรแกรมใช้การพิมพ์แบบสแตติกเมื่อทำการตรวจสอบชนิดในระหว่างการคอมไพล์เวลาซึ่งต่างจากเวลาทำงาน ในการพิมพ์คงที่ประเภทที่เกี่ยวข้องกับตัวแปรที่ไม่ใช่ค่า ภาษาที่พิมพ์แบบคงที่ ได้แก่ Ada, C, C ++, C #, JADE, Java, Fortran, Haskell, ML, Pascal, Perl (ที่เกี่ยวข้องกับสเกลาร์ที่แตกต่างอาร์เรย์อาร์เรย์แฮชและรูทีนย่อย) และ Scala การพิมพ์แบบคงที่เป็นรูปแบบที่ จำกัด ของการตรวจสอบโปรแกรม (ดูความปลอดภัยของประเภท): ดังนั้นจึงช่วยให้เกิดข้อผิดพลาดหลายประเภทที่จะถูกจับในช่วงต้นของวงจรการพัฒนา เครื่องตรวจสอบชนิดคงที่จะประเมินเฉพาะข้อมูลประเภทที่สามารถกำหนดได้ในเวลารวบรวม แต่สามารถตรวจสอบได้ว่าเงื่อนไขการตรวจสอบนั้นมีไว้สำหรับการดำเนินการที่เป็นไปได้ทั้งหมดของโปรแกรม ซึ่งไม่จำเป็นต้องตรวจสอบประเภทซ้ำทุกครั้งที่โปรแกรมทำงาน การดำเนินการโปรแกรมอาจทำให้มีประสิทธิภาพมากขึ้น (เช่นเร็วขึ้นหรือลดหน่วยความจำ) โดยไม่ตรวจสอบประเภทรันไทม์และเปิดใช้งานการปรับแต่งอื่น ๆ

เนื่องจากพวกเขาประเมินข้อมูลประเภทในระหว่างการรวบรวมและดังนั้นจึงขาดข้อมูลประเภทที่มีให้เฉพาะในเวลาทำงานตัวตรวจสอบชนิดคงที่จึงมีความระมัดระวัง พวกเขาจะปฏิเสธบางโปรแกรมที่อาจทำงานได้ดีในเวลาทำงาน แต่ไม่สามารถกำหนดแบบคงที่ให้พิมพ์ได้ดี ตัวอย่างเช่นแม้ว่านิพจน์จะประเมินค่าเป็นจริงเสมอ ณ รันไทม์โปรแกรมที่มีรหัส

if <complex test> then 42 else <type error>

จะถูกปฏิเสธตามที่พิมพ์ผิดเนื่องจากการวิเคราะห์แบบสแตติกไม่สามารถระบุได้ว่าจะไม่นำสาขาอื่นมาใช้ [1] พฤติกรรมการอนุรักษ์ของตัวตรวจสอบชนิดคงที่มีประโยชน์เมื่อประเมินเป็นเท็จนาน: ตัวตรวจสอบชนิดคงที่สามารถตรวจพบข้อผิดพลาดประเภทในเส้นทางรหัสที่ใช้บ่อย หากไม่มีการตรวจสอบประเภทคงที่การทดสอบการครอบคลุมโค้ดที่มีการครอบคลุมโค้ด 100% อาจไม่สามารถหาข้อผิดพลาดประเภทนั้น การทดสอบการครอบคลุมรหัสอาจล้มเหลวในการตรวจสอบข้อผิดพลาดประเภทดังกล่าวเนื่องจากการรวมกันของสถานที่ทั้งหมดที่มีการสร้างค่าและสถานที่ทั้งหมดที่ใช้ค่าที่แน่นอนจะต้องนำมาพิจารณา

ภาษาที่พิมพ์แบบสแตติกที่ใช้กันอย่างแพร่หลายไม่ปลอดภัยอย่างเป็นทางการ พวกเขามี "ช่องโหว่" ในข้อกำหนดภาษาการเขียนโปรแกรมทำให้โปรแกรมเมอร์สามารถเขียนโค้ดที่หลีกเลี่ยงการตรวจสอบที่ดำเนินการโดยตัวตรวจสอบชนิดแบบคงที่และเพื่อแก้ไขปัญหาที่กว้างขึ้น ตัวอย่างเช่น Java และภาษาสไตล์ C ส่วนใหญ่มีประเภทการสะกดคำและ Haskell มีคุณสมบัติเช่น unsafePerformIO: การดำเนินการดังกล่าวอาจไม่ปลอดภัยในขณะใช้งานจริงซึ่งอาจทำให้เกิดพฤติกรรมที่ไม่พึงประสงค์เนื่องจากการพิมพ์ค่าที่ไม่ถูกต้องเมื่อโปรแกรมทำงาน

การพิมพ์แบบไดนามิก

ภาษาการเขียนโปรแกรมถูกกล่าวถึงว่าพิมพ์แบบไดนามิกหรือเพียง 'ไดนามิก' เมื่อการตรวจสอบชนิดส่วนใหญ่ดำเนินการในเวลาทำงานซึ่งต่างจากการรวบรวมเวลา ในการพิมพ์แบบไดนามิกประเภทที่เกี่ยวข้องกับค่าไม่ใช่ตัวแปร ภาษาที่พิมพ์แบบไดนามิก ได้แก่ Groovy, JavaScript, Lisp, Lua, Objective-C, Perl (เกี่ยวกับประเภทที่ผู้ใช้กำหนด แต่ไม่ใช่ประเภทในตัว), PHP, Prolog, Python, Ruby, Smalltalk และ Tcl เมื่อเปรียบเทียบกับการพิมพ์แบบสแตติกการพิมพ์แบบไดนามิกอาจมีความยืดหยุ่นมากกว่า (เช่นการอนุญาตให้โปรแกรมสร้างประเภทและฟังก์ชันการทำงานตามข้อมูลเวลาทำงาน) แต่มีค่าใช้จ่ายน้อยกว่าการรับประกันแบบเบื้องต้น นี่เป็นเพราะภาษาที่พิมพ์แบบไดนามิกยอมรับและพยายามเรียกใช้บางโปรแกรมซึ่งอาจถูกพิจารณาว่าไม่ถูกต้องโดยตัวตรวจสอบชนิดคงที่

การพิมพ์แบบไดนามิกอาจส่งผลให้เกิดข้อผิดพลาดประเภทรันไทม์ - นั่นคือ ณ รันไทม์ค่าอาจมีประเภทที่ไม่คาดคิดและการดำเนินการที่ไม่เป็นไปตามประเภทนั้นจะถูกนำไปใช้ การดำเนินการนี้อาจเกิดขึ้นได้นานหลังจากสถานที่ที่มีข้อผิดพลาดในการเขียนโปรแกรมนั่นคือสถานที่ที่ข้อมูลผิดประเภทส่งผ่านไปยังสถานที่ที่ไม่ควรมี สิ่งนี้ทำให้บั๊กหายาก

ระบบภาษาที่พิมพ์แบบไดนามิกเมื่อเปรียบเทียบกับลูกพี่ลูกน้องที่พิมพ์แบบคงที่จะทำการตรวจสอบ "ซอร์สโค้ด" ที่น้อยลงในซอร์สโค้ด (แต่จะตรวจสอบตัวอย่างเช่นโปรแกรมนั้นถูกต้องทางไวยากรณ์) การตรวจสอบเวลาทำงานอาจมีความซับซ้อนมากขึ้นเนื่องจากสามารถใช้ข้อมูลแบบไดนามิกเช่นเดียวกับข้อมูลใด ๆ ที่มีอยู่ในระหว่างการรวบรวม ในอีกทางหนึ่งการตรวจสอบรันไทม์ยืนยันว่าเงื่อนไขนั้นมีอยู่ในการดำเนินการของโปรแกรมโดยเฉพาะและการตรวจสอบเหล่านี้จะถูกทำซ้ำสำหรับการดำเนินการของโปรแกรมทุกครั้ง

การพัฒนาในภาษาที่พิมพ์แบบไดนามิกมักจะได้รับการสนับสนุนโดยการปฏิบัติการเขียนโปรแกรมเช่นการทดสอบหน่วย การทดสอบเป็นหลักปฏิบัติสำคัญในการพัฒนาซอฟต์แวร์มืออาชีพและมีความสำคัญอย่างยิ่งในภาษาที่พิมพ์แบบไดนามิก ในทางปฏิบัติการทดสอบที่ทำเพื่อให้แน่ใจว่าการทำงานของโปรแกรมที่ถูกต้องสามารถตรวจจับข้อผิดพลาดในวงกว้างกว่าการตรวจสอบประเภทคงที่ แต่ในทางกลับกันไม่สามารถค้นหาข้อผิดพลาดที่ครอบคลุมทั้งการทดสอบและการตรวจสอบชนิดคงที่ การทดสอบสามารถรวมอยู่ในวัฏจักรการสร้างซอฟต์แวร์ซึ่งในกรณีนี้ถือเป็นการตรวจสอบแบบ "รวบรวมเวลา" ซึ่งผู้ใช้โปรแกรมจะไม่ต้องทำการทดสอบด้วยตนเอง

อ้างอิง

  1. เพียร์ซ, เบนจามิน (2002) ประเภทและภาษาโปรแกรม กด MIT ไอ 0-262-16209-1

75
แนวคิดหลักของ SO คือการสร้างองค์ความรู้ไม่ใช่เพื่อเชื่อมโยงไปยังที่อื่น คุณควรพยายามอย่างน้อยตัดตอนวิกิที่ตอบคำถาม
NomeN

5
ดูเหมือนจะซ้ำซ้อนเนื่องจากเป็นลิงก์ไปยังวิกิพีเดียและไม่ใช่เว็บไซต์ชั่วคราว แต่ฉันจะจำได้ว่าครั้งต่อไป
34420 Jacob

2
อย่างใดฉันยังคงไม่สามารถคิดตัวอย่างในภาษาที่พิมพ์แบบไดนามิกที่ประเภทไม่ชัดเจนในเวลารวบรวม แต่ต้องคิดออกที่รันไทม์ คุณช่วยจัดหาบางอย่างให้ฉันได้ไหม
Novellizator

3
@Novellizator ความคิดเห็นเก่า แต่ลองนึกภาพสถานการณ์ที่ข้อมูลบางอย่างถูกหยิบขึ้นมาจากเซิร์ฟเวอร์ระยะไกลจากนั้นข้อมูลนั้นจะถูกใช้เพื่อเลือกคุณสมบัติจากวัตถุ myObject[remoteDataName]Ex: จากนั้นก็ไม่มีทางรู้ได้ว่าจะเลือกทรัพย์สินประเภทใดหรือแม้ว่าจะเป็นทรัพย์สินที่ถูกต้องก็ตาม
Mike Cluck

14

คำศัพท์ "พิมพ์แบบไดนามิก" น่าเสียดายที่ทำให้เข้าใจผิด ภาษาทั้งหมดถูกพิมพ์แบบสแตติกและชนิดเป็นคุณสมบัติของนิพจน์ (ไม่ใช่ค่าที่บางคนคิด) อย่างไรก็ตามบางภาษามีเพียงประเภทเดียวเท่านั้น ภาษาเหล่านี้เรียกว่า uni-typed languages ตัวอย่างหนึ่งของภาษาเช่นนี้คือแคลคูลัสแลมบ์ดาที่ไม่ได้พิมพ์

ในแคลคูลัสแลมบ์ดาที่ยังไม่พิมพ์คำศัพท์ทั้งหมดเป็นข้อกำหนดแลมบ์ดาและการดำเนินการเพียงอย่างเดียวที่สามารถทำได้กับคำหนึ่งคือการใช้กับคำอื่น ๆ ดังนั้นการดำเนินการทั้งหมดจะส่งผลให้เกิดการเรียกซ้ำไม่สิ้นสุดหรือคำแลมบ์ดา แต่จะไม่ส่งสัญญาณข้อผิดพลาด

อย่างไรก็ตามเราได้เพิ่มแคลคูลัสแลมบ์ดาที่ไม่มีการพิมพ์ด้วยตัวเลขดั้งเดิมและการดำเนินการทางคณิตศาสตร์จากนั้นเราสามารถดำเนินการที่ไม่เกี่ยวกับสิ่ง(λx.x) + (λy.y)นั้น เราอาจโต้แย้งได้ว่าสิ่งเดียวที่ควรทำคือส่งสัญญาณข้อผิดพลาดเมื่อเกิดเหตุการณ์นี้ แต่เพื่อให้สามารถทำสิ่งนี้ได้แต่ละค่าจะต้องติดแท็กด้วยตัวบ่งชี้ที่ระบุว่าคำนั้นเป็นคำแลมบ์ดาหรือตัวเลข โอเปอเรเตอร์การเพิ่มจะตรวจสอบว่าการขัดแย้งกันทั้งสองอย่างถูกติดแท็กเป็นตัวเลขและหากไม่ใช่ให้ส่งสัญญาณข้อผิดพลาด โปรดทราบว่าแท็กเหล่านี้ไม่ใช่ประเภทเนื่องจากประเภทเป็นคุณสมบัติของโปรแกรมไม่ใช่ค่าที่ผลิตโดยโปรแกรมเหล่านั้น

ภาษาที่ไม่ได้พิมพ์ซึ่งเรียกว่าการพิมพ์แบบไดนามิก

ภาษาเช่น JavaScript, Python และ Ruby ล้วน แต่เป็นชนิดที่ไม่พิมพ์ อีกครั้งตัวtypeofดำเนินการใน JavaScript และtypeฟังก์ชันใน Python มีชื่อที่ทำให้เข้าใจผิด พวกเขากลับแท็กที่เกี่ยวข้องกับตัวถูกดำเนินการไม่ใช่ประเภทของพวกเขา ในทำนองเดียวกันdynamic_castใน C ++ และinstanceofใน Java ไม่ต้องพิมพ์การตรวจสอบ


7

รวบรวมและตีความ

"เมื่อแปลซอร์สโค้ด"

  • ซอร์สโค้ด : รหัสดั้งเดิม (โดยปกติมนุษย์พิมพ์ลงในคอมพิวเตอร์)
  • การแปล : การแปลงซอร์สโค้ดเป็นสิ่งที่คอมพิวเตอร์สามารถอ่านได้ (เช่นรหัสเครื่อง)
  • Run-Time : ช่วงเวลาที่โปรแกรมกำลังประมวลผลคำสั่ง (หลังจากรวบรวมถ้าคอมไพล์แล้ว)
  • ภาษาที่คอมไพล์ : โค้ดที่แปลก่อนรันไทม์
  • ภาษาแปล : รหัสแปลได้ทันทีระหว่างการดำเนินการ

การพิมพ์

"เมื่อตรวจสอบประเภท"

5 + '3'เป็นตัวอย่างของข้อผิดพลาดประเภทในภาษาที่พิมพ์อย่างมากเช่น Go และ Python เนื่องจากไม่อนุญาตให้ "type coercion" -> ความสามารถในการเปลี่ยนค่าในบริบทบางอย่างเช่นการรวมสองประเภท ภาษาที่พิมพ์อย่างอ่อนเช่น JavaScript จะไม่เกิดข้อผิดพลาดประเภท (ผลลัพธ์เป็น'53')

  • คงที่ : ประเภทที่ตรวจสอบก่อนเวลาทำงาน
  • แบบไดนามิก : ชนิดที่ตรวจสอบได้ทันทีขณะดำเนินการ

คำจำกัดความของ "คงที่ & รวบรวม" และ "ไดนามิก & ตีความ" ค่อนข้างคล้าย ... แต่จำไว้ว่า "เมื่อตรวจสอบประเภท" กับ "เมื่อแปลซอร์สโค้ด"

คุณจะได้รับข้อผิดพลาดประเภทเดียวกันไม่ว่าจะมีการแปลหรือแปลภาษา ! คุณต้องแยกคำเหล่านี้ตามแนวคิด


ตัวอย่าง Python

ไดนามิกแปลความหมาย

def silly(a):
    if a > 0:
        print 'Hi'
    else:
        print 5 + '3'

silly(2)

เนื่องจาก Python ถูกตีความและพิมพ์แบบไดนามิกมันจะแปลและพิมพ์รหัสตรวจสอบที่กำลังดำเนินการอยู่เท่านั้น elseบล็อกไม่เคยดำเนินการดังนั้น5 + '3'จะไม่มองแม้ที่!

เกิดอะไรขึ้นถ้ามันถูกพิมพ์แบบคงที่?

ข้อผิดพลาดประเภทจะถูกโยนก่อนที่รหัสจะทำงานได้ มันยังคงทำการตรวจสอบประเภทก่อนรันไทม์แม้ว่ามันจะถูกตีความ

เกิดอะไรขึ้นถ้ามันถูกรวบรวม?

elseบล็อกจะได้รับการแปล / มองที่ก่อนเวลาทำงาน แต่เพราะมันพิมพ์แบบไดนามิกมันจะไม่โยนความผิดพลาด! ภาษาที่พิมพ์แบบไดนามิกจะไม่ตรวจสอบประเภทจนกว่าจะมีการดำเนินการและบรรทัดนั้นจะไม่ดำเนินการ


ไปตัวอย่าง

คงที่รวบรวม

package main

import ("fmt"
)

func silly(a int) {
  if (a > 0) {
      fmt.Println("Hi")
  } else {
      fmt.Println("3" + 5)
  }
}

func main() {
  silly(2)
}

ประเภทจะถูกตรวจสอบก่อนที่จะทำงาน (คงที่) และข้อผิดพลาดประเภทจะถูกจับทันที! ประเภทจะยังคงถูกตรวจสอบก่อนรันไทม์หากถูกตีความมีผลเหมือนกัน ถ้ามันเป็นแบบไดนามิกมันจะไม่โยนข้อผิดพลาดใด ๆ แม้ว่ารหัสจะถูกมองในระหว่างการรวบรวม


ประสิทธิภาพ

ภาษาที่คอมไพล์จะมีประสิทธิภาพที่ดีขึ้นในขณะใช้งานถ้ามันถูกพิมพ์แบบคงที่ (เทียบกับแบบไดนามิก); ความรู้เกี่ยวกับประเภทช่วยให้การเพิ่มประสิทธิภาพรหัสเครื่อง

ภาษาที่พิมพ์แบบคงที่มีประสิทธิภาพที่ดีกว่าในขณะใช้งานจริงเนื่องจากไม่จำเป็นต้องตรวจสอบประเภทแบบไดนามิกขณะดำเนินการ (ตรวจสอบก่อนเรียกใช้)

ในทำนองเดียวกันภาษาที่รวบรวมจะเร็วกว่าในขณะใช้งานเนื่องจากโค้ดได้รับการแปลแล้วแทนที่จะต้อง "ตีความ" / แปลทันที

โปรดทราบว่าทั้งภาษาที่รวบรวมและพิมพ์แบบสแตติกจะมีความล่าช้าก่อนที่จะทำการแปลและการตรวจสอบประเภทตามลำดับ


ความแตกต่างเพิ่มเติม

การพิมพ์แบบคงที่จะจับข้อผิดพลาดได้ แต่เนิ่น ๆ แทนที่จะค้นหาพวกมันในระหว่างการดำเนินการ (มีประโยชน์อย่างยิ่งสำหรับโปรแกรมที่มีความยาว) มัน "เข้มงวดมากขึ้น" ซึ่งจะไม่อนุญาตให้มีข้อผิดพลาดในการพิมพ์ที่ใดก็ได้ในโปรแกรมของคุณและมักจะป้องกันตัวแปรจากการเปลี่ยนประเภทซึ่งจะป้องกันข้อผิดพลาดที่ไม่ได้ตั้งใจเพิ่มเติม

num = 2
num = '3' // ERROR

การพิมพ์แบบไดนามิกมีความยืดหยุ่นมากขึ้นซึ่งบางคนชื่นชม โดยทั่วไปจะอนุญาตให้ตัวแปรเปลี่ยนประเภทซึ่งอาจส่งผลให้เกิดข้อผิดพลาดที่ไม่คาดคิด


"เนื่องจาก Python แปลและพิมพ์แบบไดนามิกมันจะแปลและพิมพ์รหัสตรวจสอบที่ทำงานอยู่เท่านั้น " ซึ่งไม่ใช่กรณีนี้ Python (อย่างน้อยที่สุดการใช้งานอ้างอิง) จะรวบรวมรหัสทั้งหมดของคุณ ณ เวลานำเข้า (คุณสามารถรวบรวมโมดูลก่อน / ไม่นำเข้า) คอมไพเลอร์นำเสนอการเพิ่มประสิทธิภาพที่หลากหลาย (อย่างน้อยที่สุดเท่าที่ธรรมชาติอนุญาตให้มีการใช้งานของ Python)
Eli Korvigo

6

ภาษาที่พิมพ์แบบคงที่ : แต่ละตัวแปรและนิพจน์เป็นที่รู้จักกันแล้วในเวลารวบรวม

( int a;a สามารถรับเฉพาะค่าประเภทจำนวนเต็มเมื่อใช้งานจริง)

ตัวอย่าง: C, C ++, Java

ภาษาที่พิมพ์แบบไดนามิก : ตัวแปรสามารถรับค่าที่แตกต่างกัน ณ รันไทม์และประเภทของพวกเขาถูกกำหนดในเวลาทำงาน

( var a;a สามารถรับค่าชนิดใดก็ได้ในขณะทำงาน)

ตัวอย่าง: Ruby, Python


5

ภาษาที่พิมพ์แบบคงที่ตรวจสอบประเภท ณ เวลารวบรวมและประเภทไม่สามารถเปลี่ยนแปลงได้ (อย่าได้รับความน่ารักด้วยความคิดเห็นการคัดเลือกนักแสดงตัวแปร / การอ้างอิงใหม่ถูกสร้างขึ้น)

พิมพ์ภาษาแบบไดนามิกตรวจสอบชนิดของเวลาทำงานและชนิดของตัวแปรสามารถเปลี่ยนแปลงได้ในเวลาทำงาน


4

คำจำกัดความหวานและเรียบง่าย แต่เหมาะสมกับความต้องการ: ภาษาที่พิมพ์แบบคงที่จะผูกชนิดกับตัวแปรสำหรับขอบเขตทั้งหมด (Seg: SCALA) ภาษาที่พิมพ์แบบไดนามิกจะผูกประเภทกับค่าจริงที่อ้างอิงโดยตัวแปร


3
  • ในภาษาที่พิมพ์แบบคงที่ตัวแปรจะเชื่อมโยงกับชนิดซึ่งเป็นที่รู้จักกันในเวลารวบรวมและประเภทนั้นยังคงไม่เปลี่ยนแปลงตลอดการดำเนินการของโปรแกรม เท่ากับตัวแปรสามารถกำหนดค่าซึ่งเป็นตัวอย่างของประเภทที่รู้จัก / ระบุ
  • ในภาษาที่พิมพ์แบบไดนามิกตัวแปรไม่มีชนิดและค่าของมันในระหว่างการดำเนินการสามารถเป็นรูปร่างและรูปแบบใดก็ได้

2

ภาษาที่พิมพ์แบบคงที่เช่น C ++, Java และภาษาที่พิมพ์แบบไดนามิกเช่น Python แตกต่างกันเฉพาะในแง่ของการดำเนินการประเภทของตัวแปร ภาษาที่พิมพ์แบบคงที่มีชนิดข้อมูลแบบคงที่สำหรับตัวแปรที่นี่ชนิดข้อมูลถูกตรวจสอบในระหว่างการรวบรวมเพื่อการดีบักง่ายกว่ามาก ... ในขณะที่ภาษาที่พิมพ์แบบไดนามิกไม่ได้ทำแบบเดียวกันประเภทข้อมูลจะถูกตรวจสอบว่า การดีบักเป็นบิตยาก

นอกจากนี้พวกเขามีความแตกต่างเล็กมากและอาจจะเกี่ยวข้องกับการพิมพ์มั่นและพิมพ์อ่อนภาษา ภาษาที่พิมพ์อย่างรุนแรงไม่อนุญาตให้คุณใช้ประเภทหนึ่งเป็นอีกประเภทเช่น C และ C ++ ... ในขณะที่ภาษาที่พิมพ์อย่างอ่อนอนุญาตให้ใช้เช่น. python


2

พิมพ์แบบคงที่

ประเภทจะถูกตรวจสอบก่อนเวลาทำงานเพื่อให้สามารถตรวจจับข้อผิดพลาดได้ก่อนหน้านี้

ตัวอย่าง = c ++

พิมพ์แบบไดนามิก

ประเภทจะถูกตรวจสอบในระหว่างการดำเนินการ

ตัวอย่าง = Python


2
สิ่งนี้ไม่ได้เพิ่มสิ่งใด ๆ ที่ยังไม่ได้รับคำตอบอื่น ๆ ใช่หรือไม่
Robert

1
ใช่ แต่คำตอบส่วนใหญ่ไม่ชัดเจนดังนั้นฉันต้องการคำตอบที่เข้าใจง่าย
Atticus Denewmont

1

ภาษาที่พิมพ์แบบคงที่ (คอมไพเลอร์แก้ไขการเรียกเมธอดและการอ้างอิงคอมไพล์):

  • มักจะมีประสิทธิภาพที่ดีขึ้น
  • รวบรวมข้อเสนอแนะข้อผิดพลาดได้เร็วขึ้น
  • การสนับสนุน IDE ที่ดีขึ้น
  • ไม่เหมาะสำหรับการทำงานกับรูปแบบข้อมูลที่ไม่ได้กำหนด
  • ยากที่จะเริ่มการพัฒนาเมื่อโมเดลไม่ได้ถูกกำหนดไว้เมื่อใด
  • เวลารวบรวมนานขึ้น
  • ในหลายกรณีจำเป็นต้องเขียนโค้ดเพิ่มเติม

ภาษาที่พิมพ์แบบไดนามิก (การตัดสินใจในโปรแกรมกำลังทำงาน):

  • ประสิทธิภาพลดลง
  • การพัฒนาที่เร็วขึ้น
  • ข้อผิดพลาดบางอย่างอาจตรวจพบในภายหลังในเวลาทำงานเท่านั้น
  • ดีสำหรับรูปแบบข้อมูลที่ไม่ได้กำหนด (การเขียนโปรแกรมเมตา)

0

ภาษาที่พิมพ์แบบไดนามิกช่วยให้แนวคิดของอัลกอริทึมต้นแบบได้อย่างรวดเร็วโดยไม่มีค่าใช้จ่ายเกี่ยวกับการคิดว่าต้องใช้ตัวแปรชนิดใด (ซึ่งเป็นสิ่งจำเป็นในภาษาแบบคงที่ e)


-15

พิมพ์ดีดคงที่: ภาษาเช่น Java และ Scala เป็นแบบคงที่พิมพ์

ตัวแปรจะต้องมีการกำหนดและเริ่มต้นก่อนที่จะใช้ในรหัส

สำหรับอดีต int x; x = 10;

System.out.println (x);

Dynamic Typing: Perl เป็นภาษาที่พิมพ์แบบไดนามิก

ตัวแปรไม่จำเป็นต้องเริ่มต้นก่อนที่จะใช้ในรหัส

การ y = 10; ใช้ตัวแปรนี้ในส่วนของรหัสในภายหลัง


2
คำตอบนี้ไม่ถูกต้องสมบูรณ์ ในทั้งสองภาษาตัวแปรจะต้องถูกทำให้เป็น intialized ก่อนที่จะถูกใช้ อย่างไรก็ตามในภาษาที่พิมพ์แบบไดนามิกคุณอาจเลือกที่จะไม่ใช้ภาษานั้น
darshan

ดูเหมือนว่าคุณใช้คำว่า "ตัวแปร" ในทางที่ผิดคุณควรจะพูดว่า "ประเภท" แทน
ประมุข

ฉันจะยืนยันว่า Perl เป็นแบบคงที่: มันมี 3 ประเภทคือ scalar ( $), array ( @) และ hash ( %) ชนิดของตัวแปรใน Perl เป็นที่รู้จักกันในเวลารวบรวมและยังคงเหมือนเดิมตลอดอายุที่เหลือของตัวแปร
CoffeeTableEspresso
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.