ทำไม Java ไม่อนุญาตให้ใช้ส่วนหัวดังเช่นใน C ++


18

ฉันมีคำถามที่ฉันไม่พบคำตอบยกเว้นคำตอบต่อไปนี้ที่ไม่ตรงกับความต้องการของฉัน:

"เพราะเจมส์กอสลิงไม่ต้องการ"

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


14
เหตุผลที่คุณต้องการพวกเขาคืออะไร?

19
เพื่อให้มีเวลามากขึ้นสำหรับการฟันดาบ;)
dan04

6
ฉันคิดว่านักพัฒนา C ++ ส่วนใหญ่ชอบที่จะกำจัดเอ็นจิ้นการแทนที่ข้อความอายุ 40 ปีที่ซ้ำกันหลายร้อย kLoC สำหรับไฟล์ cpp ทุกไฟล์นำไปสู่การคอมไพล์ที่ยาวนานของ C ++ ในความเป็นจริงระบบโมดูลที่เหมาะสมได้รับการพิจารณาสำหรับ C ++ 11 แต่ลดลงเนื่องจากไม่มีเวลา ฉันคิดว่ามันจะเกิดขึ้นอีกครั้ง
sbi

ฉันคิดว่ามันจะเกิดขึ้นอีกครั้ง ในความเป็นจริง WG21 (คณะทำงาน ISO C ++) มีกลุ่มศึกษาเพียงเพื่อวัตถุประสงค์ในการประเมิน / พัฒนาแนวคิด "modules" เพิ่มเติม: SG2 "Modules" น่าเสียดายที่สถานะปัจจุบันไม่ได้ทำงาน
Max Truxa

คำตอบ:


46

คำตอบต่อไปนี้ที่ไม่เป็นไปตามข้อกำหนดของฉัน: "เพราะ James Gosling ไม่ต้องการ"

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

จากส่วน 2.2.1 ของเอกสารไวท์ Java Language Environment :

ซอร์สโค้ดที่เขียนด้วย Java นั้นง่ายมาก ไม่มีตัวประมวลผลล่วงหน้าไม่มี #define และความสามารถที่เกี่ยวข้องไม่มี typedef และขาดคุณสมบัติเหล่านั้นไม่จำเป็นต้องใช้ไฟล์ส่วนหัวอีกต่อไป แทนที่จะเป็นไฟล์ส่วนหัวไฟล์ต้นฉบับภาษา Java ให้คำจำกัดความของคลาสอื่น ๆ และวิธีการ

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


6
ขอขอบคุณสำหรับคำตอบของคุณส่วนหัวทำให้เกิดปัญหามากขึ้นเนื่องจาก: คำจำกัดความซ้ำซ้อนทำให้ไฟล์ต่าง ๆ ตรงกันซิงค์คำจำกัดความที่ขัดแย้งกันคำจำกัดความที่ซ่อนอยู่ นั่นเป็นสาเหตุที่ไม่ได้รับอนุญาตหรือไม่
Etienne Noël

2
โปรดทราบว่ามีการพูดคุยกันมากมายเกี่ยวกับการประชุม C ++ Commitee ครั้งต่อไปเพราะพวกเขาจะพิจารณาระบบ "โมดูล" ใหม่ที่จะเป็นระบบที่ง่ายและมีประสิทธิภาพมากกว่าการรวม (ด้วยความคล้ายคลึงกันบางอย่างกับ Java, C # ฯลฯ แพ็คเกจ) แต่ยังคงย้อนยุค - เข้ากันได้กับรวม กล่าวได้ว่าในทางทฤษฎีแล้วระบบการรวบรวมที่ดีขึ้นสามารถใช้ในการรวบรวม C ++ ได้ดีขึ้น / มีประสิทธิภาพมากขึ้น ลูกห่านที่ถูกต้องฉันเดาและ C ++ ต้องหาวิธีในการแก้ไขระบบรวมอยู่แล้ว
Klaim

5
มันใช้งานไม่ได้อย่างสมบูรณ์ ระบบการสร้าง Java ไม่สามารถระบุไฟล์ที่จะต้องคอมไพล์ใหม่หลังจากเปลี่ยนรหัส IDE จะพิจารณาว่าไฟล์ใดจำเป็นต้องมีการเปลี่ยนรหัส แต่ไม่ต้องการการคอมไพล์ซ้ำ หากลายเซ็นของเมธอดเปลี่ยนแปลง แต่การเปลี่ยนแปลงนั้นเข้ากันได้กับรหัสกับลายเซ็นเก่า (เช่นการเปลี่ยนประเภทอาร์กิวเมนต์จากการลอยเป็นสองเท่า) จำเป็นต้องมีการสร้างใหม่ทั้งหมดเพื่อป้องกัน MethodNotFoundException
kevin cline

1
@ เควิน: อย่างไรก็ตามโดยปกติแล้วมันเป็นไปได้ที่จะสร้างทุกอย่างใหม่โดยไม่ต้องเสียค่าใช้จ่ายมากเกินไป แตกต่างจาก C ++ (แต่เหมือนกับภาษาที่คอมไพล์เกือบทุกภาษา) Java ใช้เวลาไม่นานในการรวบรวมว่าการคอมไพล์บางส่วนเป็นการเพิ่มประสิทธิภาพของเวิร์กโฟลว์การพัฒนาของคุณ
Donal Fellows

1
@ Donal: มันเป็นความจริงที่ Java คอมไพล์อย่างรวดเร็ว แต่ฉันเกลียดการเดาว่าควรจะคอมไพล์ใหม่หรือไม่ งานสร้างควรทำงานทุกครั้ง
วินไคลน์

16

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

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

มีความพยายามในการสร้างสภาพแวดล้อม C ++ ที่ทุกอย่างถูกเก็บไว้ในโครงสร้างประเภทฐานข้อมูลและไม่มีไฟล์ แต่มันไม่ได้จับ


ฉันรู้ว่า แต่อย่างน้อยคุณสามารถทำได้ใน C ++ ไม่ใช่ใน Java; นั่นคือคำถามหลักของฉัน ขอบคุณสำหรับคำตอบ.
Etienne Noël

14

เนื่องจากหลักการแห้ง ใน Java ข้อมูลที่จำเป็นในการใช้คลาสในแพ็คเกจ (หรือคลาส) มีอยู่ในไฟล์. class การสร้างไฟล์ส่วนหัวแยกต่างหากที่มีข้อมูลเดียวกันจะเกี่ยวข้องกับการทำซ้ำในสองแห่ง


น่าเสียดายที่คุณมักจะต้องการทำซ้ำ - คิดถึงไฟล์ wsdl, ไฟล์ idl ฯลฯ หนึ่งอธิบายถึงอินเทอร์เฟซที่คุณสามารถใช้และไฟล์อื่นมีการใช้งาน ส่วนหัว C ++ เป็นคำจำกัดความของอินเทอร์เฟซ (ไม่ดี)
gbjbaanb

6

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

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

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

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

ดูนี่และสิ่งนี้


4

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


1

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

นอกจากนี้คอมไพเลอร์และบิลด์อาจต้องการแคชส่วนหัวที่คอมไพล์แล้วเพื่อหลีกเลี่ยงการแยกวิเคราะห์มากกว่าหนึ่งครั้ง


1
ฉันคิดว่าคุณสามารถจัดเก็บอินเทอร์เฟซในโครงการที่ใช้ร่วมกันแล้วนำไปใช้ในโครงการอิสระ
Alexander Mills
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.