ซึ่งแตกต่างจาก C ++ ใน Java เราไม่สามารถมีเพียงการประกาศฟังก์ชั่นในชั้นเรียนและคำนิยามนอกชั้นเรียน ทำไมถึงเป็นเช่นนั้น?
เป็นการเน้นว่าไฟล์เดียวใน Java ควรมีเพียงหนึ่งคลาสและไม่มีอะไรอีกหรือไม่
ซึ่งแตกต่างจาก C ++ ใน Java เราไม่สามารถมีเพียงการประกาศฟังก์ชั่นในชั้นเรียนและคำนิยามนอกชั้นเรียน ทำไมถึงเป็นเช่นนั้น?
เป็นการเน้นว่าไฟล์เดียวใน Java ควรมีเพียงหนึ่งคลาสและไม่มีอะไรอีกหรือไม่
คำตอบ:
ความแตกต่างระหว่าง C ++ และ Java คือสิ่งที่ภาษาพิจารณาหน่วยเชื่อมโยงที่เล็กที่สุดของพวกเขา
เนื่องจาก C ถูกออกแบบมาให้อยู่ร่วมกับชุดประกอบหน่วยนั้นจึงเป็นรูทีนย่อยที่เรียกโดยที่อยู่ (นี่เป็นความจริงของภาษาอื่น ๆ ที่คอมไพล์ไฟล์วัตถุดั้งเดิมเช่น FORTRAN) กล่าวอีกนัยหนึ่งอ็อบเจ็กต์ไฟล์ที่มีฟังก์ชั่นfoo()
จะมีสัญลักษณ์ที่เรียก_foo
ว่าจะแก้ไขให้เป็นอะไรยกเว้นที่อยู่เช่น0xdeadbeef
ระหว่างการเชื่อมโยง นั่นคือทั้งหมดที่มี หากฟังก์ชั่นนั้นมีการโต้แย้งก็ขึ้นอยู่กับผู้โทรเพื่อให้แน่ใจว่าทุกอย่างที่ฟังก์ชั่นคาดว่าจะเป็นไปตามลำดับก่อนที่จะเรียกที่อยู่ของมัน โดยปกติจะทำโดยการซ้อนสิ่งต่าง ๆ ลงบนสแต็กและคอมไพเลอร์จะดูแลงานเสี้ยงฮึดฮัดแสดงความไม่พอใจและตรวจสอบให้แน่ใจว่าต้นแบบตรงกับ ไม่มีการตรวจสอบสิ่งนี้ระหว่างอ็อบเจ็กต์ไฟล์ ถ้าคุณทำตามการเชื่อมโยงการโทรการโทรจะไม่ดับตามที่วางแผนไว้และคุณจะไม่ได้รับคำเตือนเกี่ยวกับมัน แม้จะมีอันตราย แต่สิ่งนี้ทำให้ไฟล์วัตถุที่รวบรวมจากหลายภาษา (รวมถึงชุดประกอบ) สามารถเชื่อมโยงเข้าด้วยกันเป็นโปรแกรมที่ใช้งานได้โดยไม่ต้องยุ่งยากมาก
C ++ แม้จะมีความเพ้อฝันเพิ่มเติมทั้งหมดก็ใช้วิธีเดียวกัน คอมไพลเลอร์ shoehorns เนมสเปซ, คลาสและเมธอด / members / etc ในการประชุมนี้โดยการทำให้เนื้อหาของคลาสเป็นชื่อเดียวที่แบนในลักษณะที่ทำให้มีลักษณะเฉพาะ ตัวอย่างเช่นเมธอดเช่นFoo::bar(int baz)
อาจเรียงเข้าด้วยกัน_ZN4Foo4barEi
เมื่อใส่ลงในอ็อบเจ็กต์ไฟล์และแอดเดรสเช่น0xBADCAFE
at runtime สิ่งนี้ขึ้นอยู่กับคอมไพเลอร์ดังนั้นหากคุณพยายามเชื่อมโยงวัตถุสองชิ้นที่มีรูปแบบการเรียงกันที่แตกต่างกันคุณจะไม่มีโชค น่าเสียดายที่เป็นเช่นนี้หมายความว่าคุณสามารถใช้extern "C"
บล็อกเพื่อปิดการใช้งาน mangling ทำให้สามารถเข้าถึงรหัสภาษา C ++ ได้อย่างง่ายดาย C ++ สืบทอดแนวคิดของฟังก์ชัน free-floating จาก C ส่วนใหญ่เนื่องจากรูปแบบวัตถุดั้งเดิมอนุญาต
Java เป็นสัตว์ที่แตกต่างที่มีชีวิตอยู่ในโลกฉนวนที่มีรูปแบบไฟล์วัตถุของตัวเอง.class
ไฟล์ ไฟล์คลาสมีข้อมูลมากมายเกี่ยวกับเนื้อหาของพวกเขาที่ช่วยให้สภาพแวดล้อมสามารถทำสิ่งต่าง ๆ กับคลาสที่รันไทม์ซึ่งกลไกการเชื่อมโยงดั้งเดิมไม่สามารถแม้แต่จะฝันถึง ข้อมูลนั้นต้องเริ่มต้นที่ไหนสักแห่งและจุดเริ่มต้นก็คือclass
. ข้อมูลที่มีอยู่ช่วยให้โค้ดที่คอมไพล์สามารถอธิบายตัวเองโดยไม่จำเป็นต้องแยกไฟล์ที่มีคำอธิบายในซอร์สโค้ดเหมือนกับที่คุณมีในภาษา C, C ++ หรือภาษาอื่น ๆ ที่ให้ประโยชน์ด้านความปลอดภัยทุกประเภทแก่คุณโดยใช้การเชื่อมโยงแบบเนทีฟแม้ในขณะรันไทม์และเป็นสิ่งที่ทำให้คุณสามารถตกปลาคลาสตามอำเภอใจออกจากไฟล์โดยใช้การสะท้อนและใช้กับความล้มเหลวที่รับประกันได้หากสิ่งที่ไม่ตรงกัน .
หากคุณยังไม่ได้คิดออกมาความปลอดภัยทั้งหมดนี้มาพร้อมกับข้อเสีย: สิ่งใดก็ตามที่คุณเชื่อมโยงกับโปรแกรม Java จะต้องเป็น Java (โดย "ลิงก์" ฉันหมายถึงทุกครั้งที่บางสิ่งในไฟล์คลาสหนึ่งอ้างถึงบางสิ่งในอีกไฟล์หนึ่ง) คุณสามารถเชื่อมโยง (ในความหมายดั้งเดิม) กับโค้ดเนทีฟโดยใช้JNIแต่มีสัญญาที่บอกเป็นนัยว่า คุณเป็นเจ้าของทั้งสองชิ้น
Java นั้นมีขนาดใหญ่และไม่ได้รวดเร็วโดยเฉพาะอย่างยิ่งกับฮาร์ดแวร์ที่มีอยู่เมื่อเปิดตัวครั้งแรกเหมือนกับที่ Ada เคยทำในทศวรรษที่ผ่านมา มีเพียง Jim Gosling เท่านั้นที่สามารถบอกได้ว่าแรงจูงใจของเขาคืออะไรในการสร้างหน่วยเชื่อมโยงที่เล็กที่สุดของคลาส Java แต่ฉันต้องเดาว่าความซับซ้อนที่เพิ่มขึ้นของการเพิ่ม floaters อิสระอาจเพิ่มเข้าไปในรันไทม์อาจเป็นฆาตกรได้
ฉันเชื่อว่าคำตอบคือตามวิกิพีเดีย Java นั้นได้รับการออกแบบมาให้เรียบง่ายและเน้นไปที่วัตถุ ฟังก์ชั่นหมายถึงการใช้งานในชั้นเรียนที่พวกเขากำหนดไว้ด้วยความคิดที่ว่าการมีฟังก์ชั่นนอกห้องเรียนไม่สมเหตุสมผล ฉันจะกระโดดไปสู่ข้อสรุปที่ Java ไม่อนุญาตเพราะมันไม่เหมาะกับ OOP บริสุทธิ์
การค้นหาโดย Google อย่างรวดเร็วสำหรับฉันไม่ได้ทำให้เกิดแรงจูงใจในการออกแบบภาษาจาวามากนัก
คำถามจริงคืออะไรจะได้รับประโยชน์จากการดำเนินการต่อในวิธี C ++ ต่อไปและจุดประสงค์ดั้งเดิมของไฟล์ส่วนหัวคืออะไร คำตอบสั้น ๆ คือรูปแบบไฟล์ส่วนหัวที่อนุญาตสำหรับการรวบรวมครั้งที่เร็วขึ้นในโครงการขนาดใหญ่ซึ่งหลายชั้นอาจจะอ้างอิงประเภทเดียวกัน ไม่จำเป็นใน JAVA และ. NET เนื่องจากลักษณะของคอมไพเลอร์
ดูคำตอบนี้ได้ที่นี่: ไฟล์ส่วนหัวดีจริงหรือ
interface
และclass
:) ไม่จำเป็นต้องมีส่วนหัว!
ไฟล์ Java หมายถึงคลาส หากคุณมีกระบวนการนอกห้องเรียนขอบเขตจะเป็นอย่างไร มันจะเป็นระดับโลกหรือไม่ หรือมันจะเป็นของชั้นที่ไฟล์ Java แทน?
สันนิษฐานว่าคุณใส่ไว้ในไฟล์ Java นั้นแทนไฟล์อื่นด้วยเหตุผล - เพราะมันไปกับคลาสนั้นมากกว่าคลาสอื่น ๆ หากขั้นตอนนอกคลาสเกี่ยวข้องกับคลาสนั้นจริงๆแล้วทำไมไม่บังคับให้เข้าไปในคลาสนั้น Java จัดการสิ่งนี้เป็นวิธีการคงที่ภายในชั้นเรียน
หากอนุญาตให้ใช้โพรซีเดอร์ภายนอกคลาสนั้นจะไม่สามารถเข้าถึงคลาสที่มีการประกาศไฟล์ได้อย่างพิเศษจึง จำกัด เฉพาะฟังก์ชันยูทิลิตี้ที่ไม่เปลี่ยนแปลงข้อมูลใด ๆ
สิ่งเดียวที่เป็นไปได้สำหรับข้อ จำกัด ของ Java นี้คือถ้าคุณมีขั้นตอนสากลที่ไม่เกี่ยวข้องกับคลาสใด ๆ คุณจะต้องสร้างคลาส MyGlobals เพื่อเก็บไว้และนำเข้าคลาสนั้นในไฟล์อื่น ๆ ทั้งหมดที่ใช้โพรซีเดอร์เหล่านั้น .
ในความเป็นจริงกลไกการนำเข้า Java ต้องการข้อ จำกัด นี้เพื่อให้สามารถทำงานได้ ด้วย API ที่มีอยู่ทั้งหมดคอมไพเลอร์ java จำเป็นต้องรู้อย่างชัดเจนว่าจะรวบรวมและอะไรที่จะคอมไพล์ดังนั้นคำสั่งการนำเข้าที่ชัดเจนที่ด้านบนของไฟล์ โดยไม่ต้องไปยังกลุ่ม Globals ของคุณให้เป็นระดับเทียมวิธีการที่คุณจะบอกคอมไพเลอร์ Java เพื่อรวบรวมของคุณ Globals และไม่ใด ๆ และทั้งหมด Globals ใน classpath ของคุณหรือไม่ สิ่งที่เกี่ยวกับการชนกันของ namespace ที่คุณมี doStuff () และคนอื่นมี doStuff ()? มันจะไม่ทำงาน บังคับให้คุณระบุ MyClass.doStuff () และ YourClass.doStuff () เพื่อแก้ไขปัญหาเหล่านี้ การบังคับให้กระบวนงานของคุณเข้าไปใน MyClass แทนภายนอกจะชี้แจงข้อ จำกัด นี้เท่านั้นและไม่ได้กำหนดข้อ จำกัด เพิ่มเติมในรหัสของคุณ
Java มีสิ่งผิดปกติหลายอย่าง - การทำให้เป็นอันดับมีหูดน้อยมากจนแทบจะเป็นเรื่องยากเกินกว่าจะเป็นประโยชน์ได้ (คิดว่า SerialVersionUID) นอกจากนี้ยังสามารถใช้ในการแบ่งซิงเกิลตันและรูปแบบการออกแบบทั่วไปอื่น ๆ เมธอด clone () บน Object ควรถูกแบ่งออกเป็น deepClone () และ mustowClone () และปลอดภัยกับประเภท คลาส API ทั้งหมดสามารถทำให้ไม่เปลี่ยนรูปโดยค่าเริ่มต้น (วิธีที่พวกเขาอยู่ใน Scala) แต่ข้อ จำกัด ที่ทุกขั้นตอนจะต้องเป็นของชั้นเรียนนั้นเป็นสิ่งที่ดี โดยมีจุดประสงค์หลักเพื่อลดความซับซ้อนของภาษาและรหัสของคุณโดยไม่ทำให้เกิดข้อ จำกัด ใด ๆ
ฉันคิดว่าคนส่วนใหญ่ที่ตอบคำถามและผู้ออกเสียงลงคะแนนเข้าใจผิด มันสะท้อนให้เห็นว่าพวกเขาไม่รู้ C ++
"คำจำกัดความ" และ "การประกาศ" เป็นคำที่มีความหมายที่เฉพาะเจาะจงมากใน C ++
OP ไม่ได้หมายถึงการเปลี่ยนวิธีการทำงานของ Java นี่เป็นคำถามเกี่ยวกับไวยากรณ์อย่างแท้จริง ฉันคิดว่ามันเป็นคำถามที่ถูกต้อง
ใน C ++ มีสองวิธีในการกำหนดฟังก์ชั่นสมาชิก
วิธีแรกคือวิธี Java เพียงใส่รหัสทั้งหมดไว้ในวงเล็บปีกกา:
class Box {
public:
// definition of member function
void change(int newInt) {
this._m = newInt;
}
private:
int _m
}
วิธีที่สอง:
class Box {
public:
// declaration of member function
void change(int newInt);
private:
int _m
}
// definition of member function
// this can be in the same file as the declaration
void Box::change(int newInt) {
this._m = newInt;
}
ทั้งสองโปรแกรมเหมือนกัน ฟังก์ชั่นchange
ยังคงเป็นฟังก์ชั่นสมาชิก: มันไม่ได้อยู่นอกชั้นเรียน นอกจากนี้นิยามคลาสต้องมีชื่อและประเภทของฟังก์ชันและตัวแปรทั้งหมดของสมาชิกเช่นเดียวกับใน Java
Jonathan Henson ถูกต้องว่านี่เป็นสิ่งประดิษฐ์ของวิธีการทำงานของส่วนหัวใน C ++: อนุญาตให้คุณใส่การประกาศในไฟล์ส่วนหัวและการนำไปใช้งานในไฟล์. cpp ที่แยกต่างหากดังนั้นโปรแกรมของคุณจะไม่ละเมิด ODR (One Definition Rule) แต่มันก็มีข้อดีอยู่ข้างนอกนั่น: มันช่วยให้คุณเห็นอินเทอร์เฟซของคลาสขนาดใหญ่ได้อย่างรวดเร็ว
ใน Java คุณสามารถประมาณเอฟเฟกต์นี้ด้วยคลาสหรืออินเตอร์เฟสแบบนามธรรม แต่สิ่งเหล่านั้นไม่สามารถมีชื่อเดียวกันกับคลาสการใช้งานซึ่งทำให้ค่อนข้างเงอะงะ
ฉันคิดว่ามันเป็นสิ่งประดิษฐ์ของกลไกการโหลดคลาส ไฟล์คลาสแต่ละไฟล์เป็นคอนเทนเนอร์สำหรับวัตถุที่โหลดได้ ไม่มีตำแหน่ง "นอก" ของไฟล์คลาส
C # ซึ่งคล้ายกับ Java จะมีคุณสมบัติชนิดนี้ผ่านการใช้วิธีการบางส่วนยกเว้นว่าวิธีการบางส่วนนั้นเป็นส่วนตัวโดยเฉพาะ
วิธีการบางส่วน: http://msdn.microsoft.com/en-us/library/6b0scde8.aspx
คลาสและวิธีการบางส่วน: http://msdn.microsoft.com/en-us/library/wa80x488.aspx
ฉันไม่เห็นเหตุผลที่ Java ไม่สามารถทำสิ่งเดียวกันได้ แต่อาจเป็นเพราะความต้องการที่รับรู้จากฐานผู้ใช้เพื่อเพิ่มคุณสมบัตินี้ให้กับภาษา
เครื่องมือสร้างรหัสส่วนใหญ่สำหรับ C # สร้างคลาสบางส่วนเพื่อให้นักพัฒนาสามารถเพิ่มโค้ดที่เขียนด้วยตนเองลงในคลาสในไฟล์แยกต่างหากได้อย่างง่ายดายหากต้องการ
C ++ กำหนดให้ข้อความทั้งหมดของคลาสถูกรวบรวมเป็นส่วนหนึ่งของหน่วยการรวบรวมทั้งหมดที่ใช้สมาชิกใด ๆ ของมันหรือสร้างอินสแตนซ์ใด ๆ วิธีเดียวที่จะรักษาเวลาที่มีสติคือการมีเนื้อหาในชั้นเรียน - เท่าที่เป็นไปได้ - เฉพาะสิ่งที่จำเป็นสำหรับผู้บริโภคเท่านั้น ความจริงที่ว่าวิธีการ C ++ มักจะเขียนนอกคลาสที่มีพวกเขาเป็นแฮ็คที่น่ารังเกียจจริงๆแรงบันดาลใจจากความจริงที่ว่าต้องใช้คอมไพเลอร์ในการประมวลผลข้อความของวิธีการเรียนทุกครั้งหนึ่งครั้งสำหรับทุกหน่วยการรวบรวม บ้าสร้างครั้ง
ใน Java ไฟล์คลาสที่คอมไพล์ประกอบด้วยข้อมูลอื่น ๆ ซึ่งเทียบเท่ากับไฟล์ C ++ .h ผู้บริโภคในชั้นเรียนสามารถดึงข้อมูลทั้งหมดที่พวกเขาต้องการจากไฟล์นั้นโดยไม่ต้องมีกระบวนการคอมไพเลอร์ไฟล์. java แตกต่างจาก C ++ ที่ไฟล์. h มีข้อมูลซึ่งมีให้สำหรับทั้งการใช้งานและไคลเอนต์ของคลาสที่อยู่ในนั้นโฟลว์ใน Java ถูกย้อนกลับ: ไฟล์ที่ไคลเอ็นต์ใช้ไม่ใช่ไฟล์ต้นฉบับที่ใช้ในการรวบรวม รหัสคลาส แต่จะผลิตแทนโดยคอมไพเลอร์โดยใช้ข้อมูลไฟล์รหัสชั้นเรียน เนื่องจากไม่จำเป็นต้องแบ่งรหัสคลาสระหว่างไฟล์ที่มีข้อมูลที่ลูกค้าต้องการและไฟล์ที่มีการนำไปใช้งาน Java จึงไม่อนุญาตให้มีการแยกดังกล่าว
ฉันคิดว่าส่วนหนึ่งของมันคือ Java เป็นภาษากีดกันที่เกี่ยวข้องกับการใช้งานในทีมขนาดใหญ่ ไม่สามารถเขียนคลาสหรือเขียนทับได้ คุณมีตัวดัดแปลงการเข้าถึง 4 ระดับที่กำหนดวิธีการที่สามารถและไม่สามารถใช้งานได้อย่างเฉพาะเจาะจง ทุกอย่างแข็งแกร่ง / พิมพ์แบบคงที่เพื่อปกป้อง devs จากประเภท hijinx ไม่ตรงกันที่เกิดจากผู้อื่นหรือตัวเอง การมีคลาสและฟังก์ชั่นเป็นหน่วยที่เล็กที่สุดของคุณทำให้ง่ายขึ้นมากในการสร้างกระบวนทัศน์ของวิธีการเกี่ยวกับการออกแบบแอพ
เปรียบเทียบกับ JavaScript ที่ฟังก์ชั่นชั้นหนึ่งของคำนาม / กริยาคู่ใช้สายฝนตกลงมาและส่งผ่านไปรอบ ๆ อย่างลูกกวาดจาก pinata-open busted คอนสตรัคชันฟังก์ชันเทียบเท่าคลาสสามารถเปลี่ยนต้นแบบเพิ่มคุณสมบัติใหม่หรือเปลี่ยนอันเก่าสำหรับอินสแตนซ์ที่ ถูกสร้างขึ้นแล้วทุกเวลาไม่มีอะไรหยุดคุณจากการแทนที่สิ่งปลูกสร้างใด ๆ ด้วยเวอร์ชันของคุณเองมี 5 ประเภทและพวกเขาจะทำการแปลงและประเมินอัตโนมัติโดยอัตโนมัติภายใต้สถานการณ์ที่แตกต่างกันและคุณสามารถแนบคุณสมบัติใหม่ ๆ
function nounAndVerb(){
}
nounAndVerb.newProperty = 'egads!';
ในที่สุดมันเป็นเรื่องของช่องและตลาด JavaScript เกี่ยวกับความเหมาะสมและหายนะในมือของ 100 (ซึ่งน่าจะปานกลาง) devs เป็น Java ครั้งหนึ่งเคยอยู่ในมือของกลุ่มเล็ก ๆ ของ devs พยายามเขียน UI เว็บด้วย เมื่อคุณทำงานกับ 100 devs สิ่งสุดท้ายที่คุณต้องการคือผู้ชายคนหนึ่งที่พลิกโฉมกระบวนทัศน์ที่ถูกสาป เมื่อคุณทำงานกับ UI หรือการพัฒนาที่รวดเร็วเป็นสิ่งที่สำคัญยิ่งกว่าสิ่งสุดท้ายที่คุณต้องการคือการกีดขวางบนการทำสิ่งที่ค่อนข้างง่ายอย่างรวดเร็วเพียงเพราะมันจะทำให้พวกเขาโง่มากหากคุณไม่ระวัง
ในตอนท้ายของวันพวกเขาทั้งสองต่างนิยมใช้ภาษาทั่วไปดังนั้นจึงมีข้อโต้แย้งทางปรัชญาอยู่บ้าง เนื้อส่วนตัวที่ใหญ่ที่สุดของฉันกับ Java และ C # คือฉันไม่เคยเห็นหรือทำงานกับ codebase แบบดั้งเดิมซึ่งผู้พัฒนาส่วนใหญ่ดูเหมือนจะเข้าใจถึงคุณค่าของ OOP พื้นฐาน เมื่อคุณเข้ามาในเกมต้องห่อทุกอย่างในชั้นเรียนบางทีมันง่ายกว่าที่จะสมมติว่าคุณกำลังทำ OOP มากกว่าฟังก์ชั่นสปาเก็ตตี้ที่ปลอมตัวเป็นโซ่ขนาดใหญ่ของชั้นเรียน 3-5 แถว
ที่กล่าวว่าไม่มีอะไรน่ากลัวไปกว่า JavaScript ที่เขียนโดยใครบางคนที่รู้ว่าเพียงพอที่จะเป็นอันตรายและไม่กลัวที่จะแสดงมันออกมา และฉันคิดว่านั่นเป็นความคิดทั่วไป ผู้ชายคนนั้นควรจะเล่นตามกฎเดียวกันใน Java ฉันจะเถียงว่าลูกนอกสมรสมักจะหาทาง