ตามที่คุณได้คาดการณ์ไว้อย่างชัดเจนแล้ว C ++ ให้ความสามารถแบบเดียวกันโดยไม่มีกลไกนั้น ดังนั้นการพูดอย่างเคร่งครัดจึงไม่จำเป็นต้องใช้กลไกtry
/finally
ที่กล่าวว่าการไม่ทำเช่นนั้นจะเป็นการกำหนดข้อกำหนดบางประการเกี่ยวกับวิธีการออกแบบภาษาที่เหลือ ใน C ++ ชุดของแอ็คชันเดียวกันจะถูกรวมอยู่ใน destructor ของคลาส สิ่งนี้ใช้งานได้เป็นหลัก (โดยเฉพาะ?) เพราะการร้องขอ destructor ใน C ++ นั้นเป็นสิ่งที่กำหนดได้ ในทางกลับกันสิ่งนี้นำไปสู่กฎที่ค่อนข้างซับซ้อนเกี่ยวกับอายุการใช้งานของวัตถุ
ภาษาอื่นส่วนใหญ่มีการรวบรวมขยะบางรูปแบบแทน ในขณะที่มีสิ่งต่าง ๆ เกี่ยวกับการรวบรวมขยะที่แย้ง (เช่นประสิทธิภาพของมันเทียบกับวิธีอื่นในการจัดการหน่วยความจำ) สิ่งหนึ่งโดยทั่วไปไม่ใช่: เวลาที่แน่นอนเมื่อวัตถุจะ "ล้าง" โดยตัวเก็บขยะไม่ได้ผูกโดยตรง ถึงขอบเขตของวัตถุ สิ่งนี้จะป้องกันการใช้งานเมื่อจำเป็นต้องทำการล้างข้อมูลเมื่อต้องการเพียงแค่การดำเนินการที่ถูกต้องหรือเมื่อจัดการกับทรัพยากรที่มีค่าดังนั้นการล้างข้อมูลของพวกเขาส่วนใหญ่จะไม่ล่าช้าโดยพลการ try
/ finally
เป็นวิธีสำหรับภาษาดังกล่าวในการจัดการกับสถานการณ์ที่ต้องมีการล้างข้อมูลที่กำหนด
ฉันคิดว่าผู้ที่อ้างว่าไวยากรณ์ C ++ สำหรับความสามารถนี้เป็น "ไม่เป็นมิตร" มากกว่า Java ค่อนข้างขาดจุด ยิ่งไปกว่านั้นพวกเขายังขาดจุดสำคัญมากเกี่ยวกับการแบ่งความรับผิดชอบซึ่งเกินกว่าไวยากรณ์และมีจำนวนมากเกี่ยวกับวิธีการออกแบบรหัส
ใน C ++ การล้างค่าที่กำหนดขึ้นนี้เกิดขึ้นใน destructor ของวัตถุ นั่นหมายความว่าวัตถุสามารถ (และโดยปกติควร) ออกแบบมาเพื่อทำความสะอาดหลังจากนั้น สิ่งนี้เป็นสาระสำคัญของการออกแบบเชิงวัตถุ - คลาสควรได้รับการออกแบบเพื่อให้เป็นนามธรรมและบังคับใช้ค่าคงที่ของมันเอง ใน C ++ เราทำอย่างนั้น - และหนึ่งในค่าคงที่ที่มันมีคือเมื่อวัตถุถูกทำลายทรัพยากรที่ควบคุมโดยวัตถุนั้น (ทั้งหมดไม่ใช่หน่วยความจำเท่านั้น) จะถูกทำลายอย่างถูกต้อง
Java (และที่คล้ายกัน) แตกต่างกันบ้าง ในขณะที่พวกเขาทำ (เรียงลำดับ) สนับสนุน a finalize
ที่สามารถให้ความสามารถในทางทฤษฎีในทำนองเดียวกันการสนับสนุนนั้นอ่อนแอมากจนไม่สามารถใช้งานได้จริง
ดังนั้นแทนที่จะเป็นคลาสเองที่สามารถทำการล้างข้อมูลที่จำเป็นได้ไคลเอ็นต์ของคลาสต้องดำเนินการตามขั้นตอนดังกล่าว หากเราทำการเปรียบเทียบสายตาสั้นอย่างพอเพียงสามารถมองเห็นได้ทันทีว่าความแตกต่างนี้ค่อนข้างน้อยและ Java ค่อนข้างแข่งขันกับ C ++ ในแง่นี้ เราจบลงด้วยสิ่งนี้ ใน C ++ คลาสจะมีลักษณะดังนี้:
class Foo {
// ...
public:
void do_whatever() { if (xyz) throw something; }
~Foo() { /* handle cleanup */ }
};
... และรหัสลูกค้ามีลักษณะดังนี้:
void f() {
Foo f;
f.do_whatever();
// possibly more code that might throw here
}
ใน Java เราแลกเปลี่ยนรหัสอีกเล็กน้อยที่วัตถุถูกใช้น้อยในชั้นเรียน นี้ในตอนแรกดูเหมือนว่าสวยแม้กระทั่งการออก ในความเป็นจริงมันอยู่ไกลจากมันเพราะในรหัสทั่วไปเรากำหนดชั้นเรียนไว้ในที่เดียวแต่เราใช้มันหลายที่ วิธี C ++ หมายถึงเราจะเขียนโค้ดนั้นเพื่อจัดการกับการล้างข้อมูลในที่เดียว วิธี Java หมายถึงเราต้องเขียนโค้ดนั้นเพื่อจัดการกับการล้างข้อมูลหลายครั้งในหลาย ๆ ที่ - ทุกที่ที่เราใช้วัตถุของคลาสนั้น
ในระยะสั้นแนวทาง Java โดยทั่วไปรับประกันได้ว่า abstractions ที่เราพยายามให้นั้นเป็น "รั่ว" - คลาสใด ๆ และทุกครั้งที่ต้องมีการล้างข้อมูลแบบกำหนดค่าจะต้องให้ลูกค้าของชั้นเรียนรู้เกี่ยวกับรายละเอียดของการล้างข้อมูลและวิธีการล้างข้อมูล แทนที่จะเป็นรายละเอียดที่ซ่อนอยู่ในชั้นเรียน
แม้ว่าฉันจะเรียกมันว่า "วิธีการของ Java" ด้านบนtry
/ finally
และกลไกที่คล้ายกันภายใต้ชื่ออื่น ๆ นั้นไม่ได้ จำกัด อยู่แค่ Java เท่านั้น สำหรับตัวอย่างที่โดดเด่นหนึ่งตัวอย่างส่วนใหญ่ (ทั้งหมด?) ของภาษา. NET (เช่น C #) จะให้ข้อมูลเดียวกัน
การทำซ้ำล่าสุดของทั้ง Java และ C # ยังให้บางสิ่งบางอย่างของจุดกึ่งกลางระหว่าง Java "คลาสสิก" และ C ++ ในเรื่องนี้ ใน C # วัตถุที่ต้องการให้การล้างข้อมูลอัตโนมัติสามารถใช้IDisposable
อินเตอร์เฟสซึ่งมีDispose
วิธีการ (อย่างน้อยราง) คล้ายกับ C + + destructor ในขณะที่สิ่งนี้สามารถใช้งานได้ผ่านทางtry
/ finally
like ใน Java, C # ทำงานโดยอัตโนมัติอีกเล็กน้อยด้วยusing
คำสั่งที่ช่วยให้คุณกำหนดทรัพยากรที่จะถูกสร้างขึ้นเมื่อมีการป้อนขอบเขตและทำลายเมื่อออกจากขอบเขต แม้ว่าจะยังอยู่ในระดับที่ไม่เพียงพอของระบบอัตโนมัติและความแน่นอนที่ได้รับจาก C ++ แต่นี่ก็ยังเป็นการพัฒนาที่เหนือกว่า Java อย่างมาก โดยเฉพาะอย่างยิ่งนักออกแบบชั้นสามารถรวบรวมรายละเอียดของวิธีการIDisposable
การกำจัดของชั้นเรียนในการดำเนินงานของ สิ่งที่เหลือสำหรับโปรแกรมเมอร์ลูกค้าคือภาระที่น้อยกว่าในการเขียนusing
คำสั่งเพื่อให้มั่นใจว่าIDisposable
อินเทอร์เฟซจะถูกใช้เมื่อมันควรจะเป็น ใน Java 7 และใหม่กว่าชื่อถูกเปลี่ยนเพื่อปกป้องผู้กระทำผิด แต่แนวคิดพื้นฐานนั้นเหมือนกันโดยทั่วไป