Tại sao Java không cho phép sử dụng các tiêu đề như trong C ++


18

Tôi có một câu hỏi mà tôi không tìm thấy câu trả lời nào ngoại trừ câu trả lời sau không đáp ứng yêu cầu của tôi:

"Bởi vì James Gosling không muốn"

Tôi biết rằng Java có thể có các giao diện (chỉ có các hàm ảo thuần túy, không có thuộc tính), nhưng nó không giống với định nghĩa lớp.


14
Lý do bạn muốn họ là gì?

19
Để có thêm thời gian cho các trận đấu kiếm;)
dan04

6
Tôi cho rằng hầu hết các nhà phát triển C ++ đều thích thoát khỏi công cụ thay thế văn bản 40 năm sao chép hàng trăm kLoC cho mỗi tệp cpp, dẫn đến thời gian biên dịch dài của C ++. Trong thực tế, một hệ thống mô-đun thích hợp đã được dự tính cho C ++ 11, nhưng đã bị loại bỏ do thiếu thời gian. Tôi cho rằng nó sẽ trở lại một lần nữa, mặc dù.
sbi

Tôi cho rằng nó sẽ trở lại một lần nữa, mặc dù. Trong thực tế, WG21 (nhóm làm việc ISO C ++) có một nhóm nghiên cứu chỉ nhằm mục đích đánh giá / phát triển khái niệm "mô-đun" hơn nữa: SG2 "Mô-đun". Quá tệ, tình trạng hiện tại của nó là không hoạt động .
Max Truxa

Câu trả lời:


46

Câu trả lời sau đây không đáp ứng yêu cầu của tôi: "Bởi vì James Gosling không muốn."

Đó là câu trả lời đúng, mặc dù. Nhóm thiết kế ngôn ngữ (Gosling, Sheridan, Naughton, sau này là Bill Joy, Ken Arnold, v.v.) đã quyết định các tiêu đề gây ra nhiều vấn đề hơn họ đã giải quyết . Vì vậy, họ đã thiết kế chúng ra, và chứng minh rằng họ có thể tạo ra một ngôn ngữ hoàn toàn hữu ích mà không cần đến chúng.

Từ Phần 2.2.1 của sách trắng Môi trường ngôn ngữ Java :

Mã nguồn được viết bằng Java rất đơn giản. Không có tiền xử lý, không có #define và các khả năng liên quan, không có typedef và không có các tính năng đó, không còn cần bất kỳ tệp tiêu đề nào nữa. Thay vì các tệp tiêu đề, các tệp nguồn ngôn ngữ Java cung cấp các định nghĩa của các lớp khác và các phương thức của chúng.

Các định nghĩa dư thừa, giữ các tệp đồng bộ hóa, các định nghĩa mâu thuẫn, các định nghĩa ẩn - không có điều nào trong số này xảy ra trong Java, vì bạn không có tiêu đề. Nếu bạn muốn xem một định nghĩa lớp trần, bạn có thể trực tiếp tạo một định nghĩa từ tệp .java - ví dụ: hầu hết các IDE sẽ hiển thị cho bạn cấu trúc của một lớp trong một thanh bên, tương đương với điều tương tự.


6
Cảm ơn câu trả lời của bạn, sau đó, các tiêu đề gây ra nhiều vấn đề hơn vì điều đó: Định nghĩa dư thừa, giữ các tệp đồng bộ, định nghĩa mâu thuẫn, định nghĩa ẩn. Có phải đó là lý do tại sao nó không được phép?
Etienne Noël

2
Lưu ý rằng có rất nhiều cuộc thảo luận về các cuộc họp Cite Commitee tiếp theo bởi vì họ sẽ xem xét một hệ thống "Mô-đun" mới sẽ là một hệ thống đơn giản và hiệu quả hơn so với bao gồm (với một số điểm tương đồng với các gói java, C #, v.v.) tương thích với bao gồm. Điều đó có nghĩa là về mặt lý thuyết, một hệ thống biên dịch tốt hơn có thể được sử dụng để làm cho quá trình biên dịch C ++ tốt hơn / hiệu quả hơn. Tôi đoán là đúng, và C ++ phải tìm cách sửa hệ thống bao gồm.
Klaim

5
Nó không hoàn toàn có thể sử dụng được. Các hệ thống xây dựng Java không thể xác định các tệp nào phải được biên dịch lại sau khi thay đổi mã. Một IDE sẽ xác định các tệp nào yêu cầu thay đổi mã, nhưng không cần biên dịch lại. Nếu chữ ký phương thức thay đổi, nhưng thay đổi tương thích mã với chữ ký cũ (ví dụ: thay đổi loại đối số từ float sang double), thì cần phải xây dựng sạch để ngăn chặn Phương thứcNotFoundException.
kevin cline

1
@kevin: Tuy nhiên, thường chỉ có thể xây dựng lại mọi thứ mà không tốn quá nhiều chi phí. Không giống như C ++ (nhưng giống như hầu hết các ngôn ngữ được biên dịch khác trên trái đất), Java không mất nhiều thời gian để biên dịch rằng biên dịch một phần là một tối ưu hóa rất đáng giá cho quy trình phát triển của bạn.
Donal Fellows

1
@Donal: Đúng là Java biên dịch khá nhanh, nhưng tôi ghét đoán xem tôi có nên thực hiện biên dịch lại đầy đủ hay không. Xây dựng chỉ nên làm việc, mọi lúc.
kevin cline

16

C ++ không có nhu cầu thực sự để có các định nghĩa và khai báo lớp trong các tệp riêng biệt. Điều đó chỉ có nghĩa là bạn ít nhất có thể quay lại trong C ngày, thực hiện phân tích cú pháp trong một lần quét mã từ trên xuống dưới. Trên các máy không có bộ nhớ truy cập ngẫu nhiên, đây là một vấn đề lớn!

Có các tiêu đề cũng cho phép bạn xuất bản giao diện lên thư viện mã của mình bằng cách cung cấp tiêu đề mà không cần tiết lộ mã nguồn. Thật không may trong C ++, bạn cũng phải tiết lộ các thành viên dữ liệu riêng tư dẫn đến các giải pháp như nỗi kinh hoàng của pimpl .

Đã có những nỗ lực để tạo ra một môi trường C ++, nơi mọi thứ được lưu trữ trong cấu trúc kiểu cơ sở dữ liệu và không có tệp nào nhưng nó không bắt kịp.


Tôi biết điều đó, nhưng ít nhất bạn có thể làm điều đó trong C ++ chứ không phải bằng Java; đó là yêu cầu chính của tôi Cảm ơn câu trả lời.
Etienne Noël

14

Vì nguyên tắc DRY . Trong Java, thông tin cần thiết để sử dụng các lớp trong một gói (hoặc lớp) được chứa trong tệp. Class. Tạo các tệp tiêu đề riêng biệt chứa cùng thông tin sẽ liên quan đến việc lặp lại nó ở hai nơi.


thật không may, bạn thường muốn lặp lại nó - nghĩ về các tệp wsdl, các tệp idl, v.v. Một mô tả giao diện bạn có thể sử dụng và một tệp khác chứa triển khai. Tiêu đề C ++ là định nghĩa giao diện (kém).
gbjbaanb

6

Trong mọi ngôn ngữ - có hai giai đoạn để tạo mã nhị phân cuối cùng - biên dịch và liên kết (tất nhiên, có tải nhưng điều đó không ảnh hưởng nhiều ở đây). Tại thời điểm biên dịch, người ta chỉ cần đặt các hook (đặc tả các hàm sẽ được gọi) ở vị trí thích hợp. Linker thực sự tham gia với họ khi cả hai mã thực sự có sẵn. Cho đến nay không có sự khác biệt giữa C ++ và Java.

, tuy nhiên, nhu cầu về C ++ phải có khai báo và định nghĩa riêng biệt. Nếu bạn giữ việc thực hiện trong tiêu đề và nếu tệp tiêu đề thay đổi, mã được liên kết với nó cần được biên dịch lại. Trong trường hợp nếu định nghĩa nằm trong tệp riêng biệt, mã chỉ cần được liên kết lại.

Hiểu rằng C ++ không có tùy chọn để có liên kết tĩnh , ngụ ý rằng mã đối tượng được cố định cùng với ứng dụng gọi điện. Xin lưu ý rằng cả trong C và C ++, không có lập trình trong tệp tiêu đề hoặc thậm chí không làm #include. nó chỉ có nghĩa là bạn cần bận tâm về cách liên kết xảy ra với các tệp đối tượng này.

Tình hình trong Java rất khác nhau. Mỗi tệp lớp được biên dịch với tệp. Class. Thật vậy, nhu cầu biên dịch hàm lớp người gọi được phục vụ như một phần tiêu đề trong tệp. Class. Tuy nhiên, trong Java liên kết cuối cùng chỉ được thực hiện bên trong Runtime (máy ảo) chỉ với đặc điểm kỹ thuật đó là mã byte của tệp lớp.

Xem cái nàycái này


4

Hiệu quả các giao diện và bao gồm là các tiêu đề; do đó, các định nghĩa giống hệt với các nhị phân và không thể đồng bộ. Đây là một trong những quyết định thiết kế tốt nhất trong Java, nhưng có một phiền toái nhỏ là không có cách nào để bó các khai báo này cho sự gọn nhẹ và nhất quán.


1

Một lý do chính đáng để bao gồm là tách mã bạn có thể muốn sử dụng lại (chẳng hạn như các định nghĩa phổ biến) khỏi mã dành riêng cho một dự án nhất định. Java muốn bạn chỉ định một lớp hoặc giao diện cho mỗi tệp và điều đó chủ yếu làm giảm nhu cầu về các tiêu đề được bao gồm - vì bạn sẽ xử lý các phần được chia sẻ đã có trong các tệp của riêng họ.

Ngoài ra, trình biên dịch và hệ thống xây dựng có thể muốn lưu trữ các tiêu đề được biên dịch trước để tránh phân tích cú pháp nhiều lần.


1
Tôi cho rằng bạn có thể lưu trữ các giao diện trong một dự án được chia sẻ và sau đó triển khai chúng trong các dự án độc lập
Alexander Mills
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.