ประเภทปลอดภัยคืออะไร


คำตอบ:


246

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

ตัวอย่างง่ายๆ:

// Fails, Trying to put an integer in a string
String one = 1;
// Also fails.
int foo = "bar";

นอกจากนี้ยังใช้กับข้อโต้แย้งวิธีเนื่องจากคุณผ่านประเภทที่ชัดเจนกับพวกเขา:

int AddTwoNumbers(int a, int b)
{
    return a + b;
}

หากฉันพยายามโทรโดยใช้:

int Sum = AddTwoNumbers(5, "5");

คอมไพเลอร์จะโยนข้อผิดพลาดเพราะฉันผ่านสตริง ("5") และคาดว่าจะเป็นจำนวนเต็ม

ในภาษาที่พิมพ์อย่างหลวม ๆ เช่น javascript ฉันสามารถทำสิ่งต่อไปนี้:

function AddTwoNumbers(a, b)
{
    return a + b;
}

ถ้าฉันเรียกมันว่าสิ่งนี้:

Sum = AddTwoNumbers(5, "5");

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

function AddTwoNumbers(a, b)
{
    return Number(a) + Number(b);
}

หรืออาจจะ:

function AddOnlyTwoNumbers(a, b)
{
    if (isNaN(a) || isNaN(b))
        return false;
    return Number(a) + Number(b);
}

ถ้าฉันเรียกมันว่าสิ่งนี้:

Sum = AddTwoNumbers(5, " dogs");

Javascript จะแปลง 5 เป็นสตริงโดยอัตโนมัติและต่อท้ายเพื่อส่งคืน "5 Dogs"

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

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

ตอนนี้กลับไปที่ C # ...

C # รองรับคุณสมบัติภาษาที่เรียกว่าความแปรปรวนร่วมโดยทั่วไปหมายความว่าคุณสามารถทดแทนประเภทฐานสำหรับประเภทย่อยและไม่ทำให้เกิดข้อผิดพลาดตัวอย่างเช่น

 public class Foo : Bar
 {
 }

ที่นี่ฉันสร้างคลาสใหม่ (Foo) subclasses Bar ตอนนี้ฉันสามารถสร้างวิธีการ:

 void DoSomething(Bar myBar)

และเรียกมันว่าใช้ Foo หรือ Bar เป็นอาร์กิวเมนต์ทั้งคู่จะทำงานโดยไม่ทำให้เกิดข้อผิดพลาด สิ่งนี้ทำงานได้เพราะ C # รู้ว่าคลาสลูกใด ๆ ของ Bar จะใช้อินเทอร์เฟซของ Bar

อย่างไรก็ตามคุณไม่สามารถทำอินเวอร์ส:

void DoSomething(Foo myFoo)

ในสถานการณ์นี้ฉันไม่สามารถส่ง Bar ไปยังวิธีนี้ได้เนื่องจากคอมไพเลอร์ไม่ทราบว่า Bar ใช้อินเตอร์เฟสของ Foo นี่เป็นเพราะคลาสย่อยสามารถ (และมักจะ) แตกต่างจากคลาสพาเรนต์มาก

แน่นอนตอนนี้ฉันได้ไปจากส่วนลึกและเกินขอบเขตของคำถามเดิม แต่สิ่งที่ดีทั้งหมดรู้ :)


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

11
สิ่งที่คุณอธิบายเรียกว่า polymorphism ไม่ใช่ความแปรปรวนร่วม ความแปรปรวนร่วมนั้นใช้ในยาชื่อสามัญ
IllidanS4 ต้องการโมนิก้ากลับเมื่อ

@NicolasRinaudo โปรดทราบว่าช่องว่างระหว่างภาษาแบบไดนามิกและแบบคงที่จะถูกกัดเซาะโดยการรวบรวมแบบไดนามิกและการคอมไพล์ล่วงหน้าสำหรับภาษา "ตีความ" และสะท้อนในภาษา "รวบรวม" Reflection อนุญาตให้ใช้การพิมพ์แบบ runtime ของเป็ดตัวอย่างเช่นภาษาที่คอมไพล์สามารถพูดว่า "เฮ้นี่มีวิธี Quack ()" ฉันจะเรียกมันและดูว่าเกิดอะไรขึ้น " ภาษาที่มีลักษณะคล้ายภาษาปาสคาลก็มักจะมีการตรวจสอบ (เกินจำเป็น) รันไทม์ล้นซึ่งนำไปสู่ข้อผิดพลาด "คอมไพเลอร์" ที่เกิดขึ้นที่รันไทม์ "ไม่สามารถพอดีกับจำนวนเต็มที่จัดหาให้ในปลายทาง 8 บิต {core dump}"
Abominator รหัส

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

คำอธิบายโดยทั่วไป v. ดี แต่ความปลอดภัยของประเภทไม่เหมือนกันอย่างยิ่ง
Senseiwu

57

ความปลอดภัยของประเภทไม่ควรสับสนกับการพิมพ์แบบคงที่ / แบบไดนามิกหรือการพิมพ์ที่แข็งแรง / อ่อนแอ

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

คำจำกัดความนี้ไม่ได้ตั้งกฎว่าด้วยเมื่อเลือกตัวเลือกนี้ มันอาจเป็นในเวลารวบรวม (พิมพ์คงที่) หรือที่รันไทม์ (พิมพ์แบบไดนามิก) ซึ่งมักจะผ่านข้อยกเว้น อาจเป็นทั้งสองอย่าง: ภาษาที่พิมพ์แบบคงที่บางตัวอนุญาตให้คุณส่งข้อมูลจากประเภทหนึ่งไปยังอีกประเภทหนึ่งและต้องตรวจสอบความถูกต้องของ casts ที่รันไทม์ (จินตนาการว่าคุณพยายามส่งObjectไปยัง a Consumer- compiler ไม่มี วิธีการรู้ว่ามันเป็นที่ยอมรับหรือไม่)

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

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


1
ตัวอย่างอื่น ๆ ของภาษาที่ไม่ปลอดภัยคืออะไร คุณหมายถึงอะไรโดย "การเขียนค่าอาร์เรย์นอกขอบเขตของอาร์เรย์มีพฤติกรรมที่ไม่ได้กำหนดโดยสเปคมันเป็นไปไม่ได้ที่จะทำนายว่าจะเกิดอะไรขึ้น" เช่นเดียวกับ Javascript มันจะกลับมาไม่ได้กำหนดใช่ไหม? หรืออะไรก็ได้ที่สามารถเกิดขึ้นได้ คุณยกตัวอย่างสิ่งนี้ได้ไหม
ARK

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

@Nicolas Rinaudo นั่นไม่ถูกต้อง คุณควรอ่านเกี่ยวกับหน่วยความจำเสมือน แต่ละกระบวนการมีพื้นที่ที่อยู่เสมือนของตนเองดังนั้นกระบวนการไม่สามารถ "เขียนทับข้อมูลของโปรแกรมอื่น" ด้วยวิธีดังกล่าว
ilstam

คุณถูกต้อง - สิ่งนี้ควรอ่านว่าคุณอาจเขียนทับส่วนอื่น ๆ ของหน่วยความจำของโปรแกรมของคุณ - ฉันเชื่อว่าตัวโปรแกรมเองและรวมถึง
Nicolas Rinaudo

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

32

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

มี 2 ​​ประเด็นหลักที่เกี่ยวข้องกับความปลอดภัยของประเภท หน่วยความจำ ** และประเภทข้อมูล (พร้อมการทำงานที่สอดคล้องกัน)

หน่วยความจำ **

charมักจะต้องใช้ 1 ไบต์ต่อตัวอักษรหรือ 8 บิต (ขึ้นอยู่กับภาษา Java และ C # ร้านตัวอักษร Unicode ซึ่งต้องใช้ 16 บิต) intต้องไบต์ที่ 4 หรือ 32 บิต (ปกติ)

สายตา:

char: |-|-|-|-|-|-|-|-|

int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

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

int >> char:

|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|

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

** ในขณะที่ปัญหาแรกนี้ไม่ได้เกี่ยวกับประเภทของข้อมูลทางเทคนิคให้พิมพ์ภาษาที่ปลอดภัยอยู่โดยเนื้อแท้และจะอธิบายปัญหาให้ผู้ที่ไม่ทราบว่าการจัดสรรหน่วยความจำ "มีลักษณะ" อย่างไร

ประเภทข้อมูล

ปัญหาที่ละเอียดและตรงประเด็นมากขึ้นคือที่ซึ่งชนิดข้อมูลสองชนิดใช้การจัดสรรหน่วยความจำเดียวกัน รับ int เทียบกับ int ที่ไม่ได้ลงนาม ทั้งสองเป็น 32 บิต (เช่นเดียวกับที่เป็นถ่าน [4] และ int ได้ง่าย แต่ปัญหาที่พบบ่อยคือ uint vs. int)

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

ภาษาที่ไม่ปลอดภัยประเภทอนุญาตให้โปรแกรมเมอร์อ้างอิงช่วงที่จัดสรรอย่างถูกต้องของ 32 บิต แต่เมื่อค่าของ int ที่ไม่ได้ลงนามถูกอ่านในช่องว่างของ int (หรือกลับกัน) เรามีundefinedพฤติกรรมอีกครั้ง ลองนึกภาพปัญหาที่อาจเกิดขึ้นในโปรแกรมการธนาคาร:

"เพื่อน! ฉันเบิกเงินเกินบัญชี $ 30 และตอนนี้ฉันเหลือ $ 65,506 !!"

... 'แน่นอนโปรแกรมธนาคารใช้ประเภทข้อมูลที่ใหญ่กว่ามาก ;) ฮ่า ๆ!

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

ความเร็วเทียบกับความปลอดภัย

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

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


27

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

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


1
รอนิยามของประเภทความปลอดภัยไม่ได้คำเดียว "type": if no operation leads to undefined behaviorD
VasiliNovikov

1
นอกจากนี้ฉันจะไม่เห็นด้วยกับคำจำกัดความดังกล่าว ฉันคิดว่าประเภทความปลอดภัยหมายถึง 1. การมีอยู่ของประเภท 2. ความรู้ของพวกเขาต่อคอมไพเลอร์และการตรวจสอบที่เหมาะสมแน่นอน
VasiliNovikov

10

ภาษาการเขียนโปรแกรมที่เป็น 'ชนิดปลอดภัย' หมายถึงสิ่งต่าง ๆ ต่อไปนี้:

  1. คุณไม่สามารถอ่านจากตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้น
  2. คุณไม่สามารถสร้างดัชนีอาร์เรย์ได้เกินขอบเขต
  3. คุณไม่สามารถดำเนินการปลดเปลื้องประเภทไม่ได้ตรวจสอบ

8

คำอธิบายจากเอกศิลปศาสตร์ไม่ใช่วิชาเอกวิทยาศาสตร์:

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

ตัวอย่างเช่นใน C # ฉันกำหนดฟังก์ชันเป็น:

 void foo(int arg)

คอมไพเลอร์จะหยุดฉันจากการทำเช่นนี้:

  // call foo
  foo("hello world")

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

พิมพ์ภาษาที่ปลอดภัยพยายามที่จะจับมากขึ้นใน "เวลารวบรวม"

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


4
ศิลปศาสตร์ที่สำคัญจะบอกว่าคำอธิบาย :) นอกจากนี้คุณยังมหันต์พิมพ์แบบคงที่และแบบไดนามิก
ididak

1
ศิลปศาสตร์ "เอก" ไม่ใช่ "เอก"
Corey Trager

5

หากต้องการความเข้าใจที่ดียิ่งขึ้นโปรดดูวิดีโอด้านล่างซึ่งแสดงรหัสในภาษาที่ปลอดภัย (C #) และไม่พิมพ์ภาษาที่ปลอดภัย (javascript)

http://www.youtube.com/watch?v=Rlw_njQhkxw

ตอนนี้สำหรับข้อความยาว

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

ตัวอย่างเช่น JavaScript ไม่ใช่ภาษาที่ปลอดภัยสำหรับพิมพ์ ในโค้ดด้านล่าง“ num” เป็นตัวแปรที่เป็นตัวเลขและ“ str” คือสตริง Javascript อนุญาตให้ฉันทำ "num + str" ตอนนี้ GUESS จะทำเลขคณิตหรือการต่อข้อมูล

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

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

<script>
var num = 5; // numeric
var str = "5"; // string
var z = num + str; // arthimetic or concat ????
alert(z); // displays  “55”
</script>

C # เป็นภาษาที่ปลอดภัยประเภท ไม่อนุญาตให้กำหนดชนิดข้อมูลหนึ่งให้กับชนิดข้อมูลอื่น รหัสด้านล่างไม่อนุญาตให้ตัวดำเนินการ“ +” สำหรับข้อมูลชนิดต่าง ๆ

ป้อนคำอธิบายรูปภาพที่นี่


4

Type-safe หมายความว่าโดยทางโปรแกรมชนิดของข้อมูลสำหรับตัวแปรค่าส่งคืนหรืออาร์กิวเมนต์ต้องพอดีภายในเกณฑ์ที่แน่นอน

ในทางปฏิบัติหมายความว่า 7 (ชนิดจำนวนเต็ม) แตกต่างจาก "7" (อักขระที่ยกมาของสตริงประเภท)

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

C / C ++ / Java จะไม่เข้าใจหรือจะต่อผลลัพธ์เป็น "73" แทน ความปลอดภัยประเภทป้องกันข้อบกพร่องประเภทนี้ในรหัสโดยทำให้ความต้องการประเภทที่ชัดเจน

ประเภทความปลอดภัยมีประโยชน์มาก วิธีแก้ปัญหาข้างต้น "7" + 3 คือการพิมพ์ cast (int) "7" + 3 (เท่ากับ 10)


3

แนวคิด:

เพื่อให้ง่ายต่อการพิมพ์ปลอดภัยเหมือนความหมายมันทำให้แน่ใจว่าประเภทของตัวแปรควรจะปลอดภัยเช่น

  1. ไม่มีชนิดข้อมูลที่ไม่ถูกต้องเช่นไม่สามารถบันทึกหรือเริ่มต้นตัวแปรชนิดสตริงด้วยจำนวนเต็ม
  2. ไม่สามารถเข้าถึงดัชนีนอกขอบเขตได้
  3. อนุญาตเฉพาะตำแหน่งหน่วยความจำเฉพาะ

ดังนั้นทั้งหมดเกี่ยวกับความปลอดภัยของประเภทของที่เก็บข้อมูลของคุณในแง่ของตัวแปร


2

ลองคำอธิบายนี้ใน ...

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

สำหรับพฤติกรรมที่ไม่ปลอดภัยให้พิจารณาสิ่งนี้:

object x = 89;
int y;

หากคุณพยายามทำสิ่งนี้:

y = x;

คอมไพเลอร์โยนข้อผิดพลาดที่ระบุว่าไม่สามารถแปลง System.Object เป็น Integer คุณต้องทำอย่างชัดเจน วิธีหนึ่งจะเป็น:

y = Convert.ToInt32( x );

การมอบหมายข้างต้นไม่ปลอดภัย การกำหนด typesafe คือประเภทที่สามารถกำหนดให้กันได้โดยตรง

คอลเลกชัน typesafe ที่ไม่อุดมสมบูรณ์ใน ASP.NET (เช่นแอปพลิเคชันเซสชันและคอลเลกชัน viewstate) ข่าวดีเกี่ยวกับการรวบรวมเหล่านี้คือ (ลดการพิจารณาการจัดการสถานะเซิร์ฟเวอร์หลายครั้ง) คุณสามารถใส่ชนิดข้อมูลใด ๆ ลงในคอลเลกชันสามรายการใดก็ได้ ข่าวร้าย: เนื่องจากคอลเลกชันเหล่านี้ไม่ปลอดภัยคุณจะต้องส่งค่าที่เหมาะสมเมื่อดึงออกมา

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

Session[ "x" ] = 34;

ทำงานได้ดี แต่หากต้องการกำหนดค่าจำนวนเต็มกลับคุณจะต้อง:

int i = Convert.ToInt32( Session[ "x" ] );

อ่านเกี่ยวกับข้อมูลทั่วไปเกี่ยวกับวิธีการอำนวยความสะดวกที่ช่วยให้คุณสามารถใช้คอลเลกชัน typesafe ได้อย่างง่ายดาย

C # เป็นภาษา typesafe แต่คอยดูบทความเกี่ยวกับ C # 4.0; ความเป็นไปได้แบบไดนามิกที่น่าสนใจมีมากมาย (มันเป็นสิ่งที่ดีที่ C # ได้รับตัวเลือกที่เข้มงวด: ปิด ... เราจะเห็น)


โดยส่วนตัวแล้วฉันเกลียดการแปลงหากต้องการสัญกรณ์ทำไมคุณไม่ใช้แค่นักแสดงที่ปลอดภัย? ฟังก์ชั่นการโทรที่น้อยลงเท่านั้นใน callstack เช่นกัน
FlySwat

2

ประเภทที่ปลอดภัยคือรหัสที่เข้าถึงได้เฉพาะตำแหน่งหน่วยความจำที่ได้รับอนุญาตให้เข้าถึงและในรูปแบบที่กำหนดไว้และอนุญาตเท่านั้น รหัสประเภทความปลอดภัยไม่สามารถทำการดำเนินการกับวัตถุที่ไม่ถูกต้องสำหรับวัตถุนั้น คอมไพเลอร์ภาษา C # และ VB.NET มักจะสร้างรหัสประเภทที่ปลอดภัยซึ่งได้รับการตรวจสอบว่าเป็นประเภทที่ปลอดภัยในระหว่างการรวบรวม JIT


คุณหมายถึงความปลอดภัยของหน่วยความจำหรือไม่?
golopot

1

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

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

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

ภาษาที่ใช้การพิมพ์แบบไดนามิก (หรือการพิมพ์แบบเป็ดหรือการพิมพ์อย่างชัดแจ้ง) เช่น Perl, Python, Ruby, SQLite และ Lua ไม่มีแนวคิดของตัวแปรที่พิมพ์ สิ่งนี้บังคับให้โปรแกรมเมอร์เขียนรูทีนการตรวจสอบความถูกต้องรันไทม์สำหรับตัวแปรทุกตัวเพื่อให้แน่ใจว่าถูกต้องหรือทนต่อผลที่ตามมาของข้อยกเว้นรันไทม์ที่ไม่ได้อธิบาย จากประสบการณ์ของฉันโปรแกรมเมอร์ในภาษาที่พิมพ์แบบคงที่เช่น C, C ++, Java และ C # มักจะคิดว่าประเภทที่กำหนดแบบคงที่คือสิ่งที่พวกเขาต้องทำเพื่อให้ได้ประโยชน์จากความปลอดภัยของประเภท สิ่งนี้ไม่เป็นความจริงสำหรับโปรแกรมคอมพิวเตอร์ที่มีประโยชน์มากมายและเป็นการยากที่จะคาดการณ์ว่ามันจะเป็นจริงสำหรับโปรแกรมคอมพิวเตอร์ใด ๆ

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


2
ตัวแปรหลามพิมพ์ ( ขอพิมพ์ในความเป็นจริง) ลองทำเช่นนี้: "str" ​​+ 1 คุณจะได้รับข้อผิดพลาด อย่างไรก็ตามประเภทจะถูกตรวจสอบที่รันไทม์แทนที่จะรวบรวมเวลา
mipadi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.