อ่าน 4 นาที
การชกมวย (การเขียนโปรแกรมคอมพิวเตอร์)
ใน วิทยาการคอมพิวเตอร์ การ บ็อกซิ่ง (หรือที่เรียกว่าการห่อหุ้ม) คือการแปลงค่าประเภทพื้นฐานโดยการบรรจุค่าลงใน อ็อบเจ็กต์ เพื่อให้สามารถใช้ค่าดังกล่าวเป็น ตัวอ้างอิงได้ ส่วน การ...
การชกมวย (การเขียนโปรแกรมคอมพิวเตอร์)
ในวิทยาการคอมพิวเตอร์การบ็อกซิ่ง (หรือที่เรียกว่าการห่อหุ้ม) คือการแปลงค่าประเภทพื้นฐานโดยการบรรจุค่าลงในอ็อบเจ็กต์เพื่อให้สามารถใช้ค่าดังกล่าวเป็นตัวอ้างอิงได้ ส่วนการอันบ็อกซิ่งคือการแปลงกลับโดยการดึงค่าพื้นฐานออกจากอ็อบเจ็กต์ที่ห่อหุ้มมันไว้ และการออโต้บ็อกซิ่งคือคำที่ใช้เรียกการทำการแปลงบ็อกซิ่งและ/หรืออันบ็อกซิ่งโดยอัตโนมัติเมื่อจำเป็น
มวย
การใช้งาน Boxing ที่โดดเด่นที่สุดคือในภาษา Javaซึ่งมีการแยกความแตกต่างระหว่าง ประเภท อ้างอิงและประเภทค่าด้วยเหตุผลต่างๆ เช่น ประสิทธิภาพในการทำงาน และปัญหาด้านไวยากรณ์และความหมาย ใน Java จะต้องเป็นอินสแตนซ์ของเราอาจต้องการมีแต่สิ่งนี้เป็นไปไม่ได้โดยตรง แทนที่จะเป็นเช่นนั้น Java จึงกำหนดคลาส Wrapperสำหรับประเภทพื้นฐาน แต่ละประเภท เช่นและและและเป็นต้นโดยใช้ ประเภทพารามิเตอร์ ทั่วไปที่แนะนำในJ2SE 5.0 เราสามารถกำหนดและแทรกค่าลงในรายการโดย Boxing ค่าเหล่านั้นเป็นอ็อบเจ็กต์ ได้LinkedList<T>TObjectLinkedList<int>IntegerintCharactercharFloatfloatLinkedList<Integer>intInteger
ในทางกลับกันC#ไม่มีคลาส wrapper สำหรับค่าพื้นฐาน แต่ยอมให้มีการแปลงค่าใดๆ ก็ได้เป็น boxing โดยส่งคืนObjectค่าอ้างอิงทั่วไป ในObjective-Cค่าพื้นฐานใดๆ ก็สามารถนำคำนำหน้าด้วย `type` @เพื่อสร้างNSNumber`type` ขึ้นมาได้ (เช่น `type` @123หรือ`type`) ซึ่งช่วยให้สามารถเพิ่มค่าเหล่านั้นลงในคอลเลกชันมาตรฐานใดๆ ก็ได้ เช่น ` item` @(123)NSArray
Haskellแทบไม่มีแนวคิดเกี่ยวกับประเภทอ้างอิงแต่ยังคงใช้คำว่า "boxed" สำหรับการแสดง ตัวชี้ไปยัง ยูเนียนที่มีแท็ก แบบสม่ำเสมอของระบบรันไทม์ [ 1 ]
อ็อบเจ็กต์ที่ถูกบรรจุ (boxed object) จะเป็นสำเนาของอ็อบเจ็กต์ค่า (value object) เสมอ และโดยปกติจะไม่สามารถเปลี่ยนแปลงได้ (immutable ) การแกะอ็อบเจ็กต์ (unboxing) ก็จะได้สำเนาของค่าที่เก็บไว้เช่นกัน การบรรจุและการแกะอ็อบเจ็กต์ซ้ำๆ อาจส่งผลกระทบอย่างรุนแรงต่อประสิทธิภาพการทำงาน เนื่องจากกระบวนการบรรจุจะสร้างอ็อบเจ็กต์ใหม่แบบไดนามิก และการแกะอ็อบเจ็กต์ (หากค่าที่ถูกบรรจุไม่ได้ใช้งานอีกต่อไป) จะทำให้พวกมันพร้อมสำหรับการเก็บขยะ (garbage collection) อย่างไรก็ตาม ตัวเก็บขยะสมัยใหม่ เช่น ตัวเก็บขยะ HotSpot ของ Java สามารถเก็บขยะอ็อบเจ็กต์ที่มีอายุสั้นได้อย่างมีประสิทธิภาพมากขึ้น ดังนั้นหากอ็อบเจ็กต์ที่ถูกบรรจุมีอายุสั้น ผลกระทบต่อประสิทธิภาพการทำงานอาจไม่รุนแรงนัก
ในบางภาษา มีความเท่าเทียมกันโดยตรงระหว่างชนิดข้อมูลพื้นฐานที่ไม่ถูกบรรจุ (unboxed primitive type) กับการอ้างอิงถึงชนิดข้อมูลอ็อบเจ็กต์ที่ไม่สามารถเปลี่ยนแปลงได้ (immutable, boxed object type) อันที่จริงแล้ว เป็นไปได้ที่จะแทนที่ชนิดข้อมูลพื้นฐานทั้งหมดในโปรแกรมด้วยชนิดข้อมูลอ็อบเจ็กต์ที่ถูกบรรจุ ในขณะที่การกำหนดค่าจากชนิดข้อมูลพื้นฐานหนึ่งไปยังอีกชนิดข้อมูลพื้นฐานหนึ่งจะคัดลอกค่าของมัน การกำหนดค่าจากการอ้างอิงถึงอ็อบเจ็กต์ที่ถูกบรรจุหนึ่งไปยังอีกอ็อบเจ็กต์หนึ่งจะคัดลอกค่าการอ้างอิงเพื่อให้ชี้ไปยังอ็อบเจ็กต์เดียวกันกับการอ้างอิงครั้งแรก อย่างไรก็ตาม สิ่งนี้จะไม่ก่อให้เกิดปัญหาใดๆ เนื่องจากอ็อบเจ็กต์นั้นไม่สามารถเปลี่ยนแปลงได้ ดังนั้นในเชิงความหมายจึงไม่มีความแตกต่างที่แท้จริงระหว่างการอ้างอิงสองครั้งไปยังอ็อบเจ็กต์เดียวกันหรือไปยังอ็อบเจ็กต์ที่แตกต่างกัน (เว้นแต่คุณจะพิจารณาความเท่าเทียมกันทางกายภาพ) สำหรับการดำเนินการทั้งหมดนอกเหนือจากการกำหนดค่า เช่น การคำนวณทางคณิตศาสตร์ การเปรียบเทียบ และตัวดำเนินการตรรกะ เราสามารถถอดชนิดข้อมูลที่ถูกบรรจุออก ทำการดำเนินการ และบรรจุผลลัพธ์กลับเข้าไปใหม่ได้ตามต้องการ ดังนั้นจึงเป็นไปได้ที่จะไม่จัดเก็บชนิดข้อมูลพื้นฐานเลย
ออโต้บ็อกซิ่ง
Autoboxing คือคำที่ใช้เรียกการแปลงประเภทข้อมูลจากประเภทค่าไปเป็นประเภทอ้างอิง (ทั้งแบบโดย ปริยายหรือโดยชัดแจ้ง) คอมไพเลอร์จะสร้างซอร์สโค้ดเพิ่มเติมเพื่อสร้างอ็อบเจ็กต์โดยอัตโนมัติ
ตัวอย่างเช่น ใน Java เวอร์ชันก่อน J2SE 5.0 โค้ดต่อไปนี้จะไม่สามารถคอมไพล์ได้:
Integer i = new Integer ( 9 ); Integer i = 9 ; // เกิดข้อผิดพลาดในเวอร์ชันก่อน 5.0!คอมไพเลอร์ก่อนเวอร์ชัน 5.0 จะไม่ยอมรับบรรทัดสุดท้ายIntegerเป็นอ็อบเจ็กต์อ้างอิง ซึ่งโดยพื้นฐานแล้วไม่แตกต่างจากList, Object, และอื่นๆ ในการแปลงจากintเป็นIntegerจะต้องสร้างอินสแตนซ์ของอ็อบเจ็กต์ Integer ด้วยตนเอง ตั้งแต่ J2SE 5.0 เป็นต้นไป คอมไพเลอร์จะยอมรับบรรทัดสุดท้าย และแปลงโดยอัตโนมัติเพื่อให้สร้างอ็อบเจ็กต์ Integer เพื่อเก็บค่า9[ 2 ] ซึ่งหมายความว่า ตั้งแต่ J2SE 5.0 เป็นต้นไป บางอย่างเช่นโดยที่และเป็นจะสามารถคอมไพล์ได้แล้ว — a และ b จะถูกแยกกล่อง ค่าจำนวนเต็มจะถูกบวกเข้าด้วยกัน และผลลัพธ์จะถูกแยกกล่องอัตโนมัติเป็น ใหม่ซึ่งในที่สุดจะถูกเก็บไว้ในตัวแปรไม่สามารถใช้ตัวดำเนินการความเท่าเทียมกันในลักษณะนี้ได้ เนื่องจากตัวดำเนินการความเท่าเทียมกันถูกกำหนดไว้แล้วสำหรับประเภทอ้างอิง สำหรับความเท่าเทียมกันของการอ้างอิง ในการทดสอบความเท่าเทียมกันของค่าในประเภทกล่อง จะต้องแยกกล่องด้วยตนเองและเปรียบเทียบค่าพื้นฐาน หรือใช้วิธี การIntegerc=a+babIntegerIntegercObjects.equals
อีกตัวอย่างหนึ่ง: J2SE 5.0 อนุญาตให้โปรแกรมเมอร์จัดการกับคอลเลกชัน (เช่นLinkedList) ราวกับว่ามันมีintค่าแทนที่จะเป็นIntegerอ็อบเจ็กต์ ซึ่งไม่ได้ขัดแย้งกับสิ่งที่กล่าวไว้ข้างต้น: คอลเลกชันยังคงมีเพียงการอ้างอิงถึงอ็อบเจ็กต์แบบไดนามิก และไม่สามารถแสดงรายการประเภทพื้นฐานได้ มันไม่สามารถเป็น ได้แต่ต้องเป็นแทน อย่างไรก็ตาม คอมไพเลอร์จะแปลงโค้ดโดยอัตโนมัติเพื่อให้รายการรับอ็อบเจ็กต์ได้โดย "เงียบๆ" ในขณะที่ซอร์สโค้ดกล่าวถึงเฉพาะค่าพื้นฐานเท่านั้น ตัวอย่างเช่น ตอนนี้โปรแกรมเมอร์สามารถเขียนและคิดราวกับว่าถูกเพิ่มเข้าไปในรายการแล้ว แต่จริงๆ แล้วคอมไพเลอร์จะแปลงบรรทัดนั้นให้เป็น LinkedList<int>LinkedList<Integer>list.add(3)int3list.add(newInteger(3))
การแกะกล่องอัตโนมัติ
ด้วยการแกะกล่องอัตโนมัติ คอมไพเลอร์จะเพิ่มโค้ดต้นฉบับเพิ่มเติมโดยอัตโนมัติ เพื่อดึงค่าออกมาจากอ็อบเจ็กต์นั้น ไม่ว่าจะโดยการเรียกใช้เมธอดบางอย่างบนอ็อบเจ็กต์นั้น หรือโดยวิธีการอื่น ๆ
ตัวอย่างเช่น ใน Java เวอร์ชันก่อน J2SE 5.0 โค้ดต่อไปนี้จะไม่สามารถคอมไพล์ได้:
Integer k = new Integer ( 4 ); int l = k . intValue (); // ถูกต้องเสมอint m = k ; // เดิมทีน่าจะเป็นข้อผิดพลาด แต่ตอนนี้ถูกต้องแล้วC# ไม่รองรับการแปลงค่าอัตโนมัติ (automatic unboxing) ในความหมายเดียวกับ Java เพราะไม่มีชุดประเภทข้อมูลพื้นฐาน (primitive types) และประเภทข้อมูลเชิงวัตถุ (object types) แยกต่างหาก ประเภทข้อมูลที่มีทั้งเวอร์ชันพื้นฐานและเชิงวัตถุใน Java จะถูกคอมไพเลอร์ของ C# นำไปใช้โดยอัตโนมัติเป็นประเภทข้อมูลพื้นฐาน (ค่า) หรือประเภทข้อมูลเชิงวัตถุ (อ้างอิง) อย่างใดอย่างหนึ่ง
ในทั้งสองภาษา การแปลงประเภทข้อมูลอัตโนมัติจะไม่ลดประเภทข้อมูลโดยอัตโนมัติ กล่าวคือ โค้ดต่อไปนี้จะไม่สามารถคอมไพล์ได้:
ซี#:
int i = 42 ; object o = i ; // ใส่กล่องint j = o ; // แกะกล่อง (เกิดข้อผิดพลาด) Console.WriteLine ( j ); // บรรทัดที่ไม่สามารถเข้าถึง ได้ผู้เขียนอาจคาดหวังผลลัพธ์ "42"จาวา:
int i = 42 ; Object o = i ; // เก็บค่าลงในกล่องint j = o; // แกะกล่อง (เกิดข้อผิดพลาด) System.out.println( j ) ; // บรรทัดที่ไม่สามารถเข้าถึงได้ผู้เขียน อาจคาดหวังผลลัพธ์ " 42"มวยสนิม
RustมีBoxประเภทที่แสดงถึงค่าที่จัดสรรบนฮีปซึ่งเป็นเจ้าของเพียงผู้เดียว: [ 3 ]
let number : Box < i32 > = Box :: new ( 42 );std::boxed::Boxใน Rust นั้นเทียบเท่ากับstd::unique_ptrในC++ ซึ่ง เป็น ตัวชี้อัจฉริยะชนิดหนึ่ง
โดยใช้std :: unique_ptr ;unique_ptr < int > number = std :: make_unique < int > ( 42 );หากค่าจำเป็นต้องมีการเป็นเจ้าของร่วมกัน (เช่น ระหว่างเธรด) สามารถใช้Arcซึ่งแสดงถึงค่าที่จัดสรรบนฮีปโดยนับการอ้างอิง[ 4 ] [ 5 ]ซึ่งคล้ายกับstd::shared_ptrใน C++
ตัวช่วยพิมพ์
ภาษา Object Pascalสมัยใหม่มีอีกวิธีหนึ่งในการดำเนินการกับชนิดข้อมูลพื้นฐาน ซึ่งคล้ายกับการบ็อกซิ่ง เรียกว่าตัวช่วยชนิดข้อมูล (type helpers) ในFreePascalหรือตัวช่วยบันทึก (record helpers) ในDelphiและFreePascalในโหมด Delphi ภาษาที่กล่าวถึงเป็นภาษาคอมไพล์ของ Object Pascal ไปยังภาษาเนทีฟ ดังนั้นจึงขาดคุณสมบัติบางอย่างที่ C# และ Java สามารถใช้งานได้ โดยเฉพาะอย่างยิ่ง การอนุมานชนิดข้อมูล ขณะรันไทม์สำหรับตัวแปรที่มีชนิดข้อมูลที่เข้มงวด แต่คุณสมบัตินี้เกี่ยวข้องกับการบ็อกซิ่ง ช่วยให้โปรแกรมเมอร์สามารถใช้โครงสร้างต่างๆ เช่น
{$ifdef fpc}{$mode delphi}{$endif} uses sysutils ; // หน่วยนี้ประกอบด้วย wraps สำหรับประเภทข้อมูลพื้นฐานvar x : integer = 100 ; s : string ; begin s := x . ToString ; writeln ( s ) ; end .สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ การชกมวย (การเขียนโปรแกรมคอมพิวเตอร์)
ใน วิทยาการคอมพิวเตอร์ การ บ็อกซิ่ง (หรือที่เรียกว่าการห่อหุ้ม) คือการแปลงค่าประเภทพื้นฐานโดยการบรรจุค่าลงใน อ็อบเจ็กต์ เพื่อให้สามารถใช้ค่าดังกล่าวเป็น ตัวอ้างอิงได้ ส่วน การ...
มวย
การใช้งาน Boxing ที่โดดเด่นที่สุดคือใน ภาษา Java ซึ่งมีการแยกความแตกต่างระหว่าง ประเภท อ้างอิง และ ประเภทค่า ด้วยเหตุผลต่างๆ เช่น ประสิทธิภาพในการทำงาน และปัญหาด้านไวยากรณ์และความหมาย ใน Java จะต้องเป็นอินสแตนซ์ของเราอาจต้องการมีแต่สิ่งนี้เป็นไปไม่ได้โดยตรง...
ออโต้บ็อกซิ่ง
Autoboxing คือคำที่ใช้เรียกการแปลงประเภทข้อมูลจากประเภทค่าไปเป็นประเภทอ้างอิง (ทั้งแบบโดย ปริยาย หรือโดยชัดแจ้ง) คอมไพเลอร์จะสร้างซอร์สโค้ดเพิ่มเติมเพื่อสร้างอ็อบเจ็กต์โดยอัตโนมัติ
การแกะกล่องอัตโนมัติ
ด้วยการแกะกล่องอัตโนมัติ คอมไพเลอร์จะเพิ่มโค้ดต้นฉบับเพิ่มเติมโดยอัตโนมัติ เพื่อดึงค่าออกมาจากอ็อบเจ็กต์นั้น ไม่ว่าจะโดยการเรียกใช้เมธอดบางอย่างบนอ็อบเจ็กต์นั้น หรือโดยวิธีการอื่น ๆ