Làm thế nào trình biên dịch biết về các lớp khác và các thuộc tính của chúng?


14

Tôi đang viết ngôn ngữ lập trình đầu tiên của mình là hướng đối tượng và cho đến nay rất tốt với việc tạo một 'lớp' duy nhất. Nhưng, hãy nói rằng tôi muốn có các lớp học, nói ClassAClassB. Với điều kiện hai người này không có gì để làm với nhau thì tất cả đều tốt. Tuy nhiên, nói ClassAtạo ra một ClassB- điều này đặt ra 2 câu hỏi liên quan:

-Làm thế nào sẽ trình biên dịch bí quyết khi biên dịch ClassAClassBthậm chí tồn tại, và, nếu có, làm thế nào để nó biết tính chất của nó?

Suy nghĩ của tôi cho đến nay là: thay vì biên dịch từng lớp một (ví dụ quét, phân tích và tạo mã) mỗi tệp "(không thực sự là tệp, mỗi lần, nhưng" lớp ") trước tiên tôi cần quét + phân tích cú pháp , sau đó tạo mã cho tất cả?

Câu trả lời:


13

Các ngôn ngữ khác nhau (và do đó trình biên dịch) tiếp cận điều này khác nhau.

Trong họ C, các mô-đun khác nhau có tệp tiêu đề tương ứng được sử dụng trong khi xây dựng đối tượng. Các tệp tiêu đề cung cấp thông tin về kích thước của đối tượng và những chức năng hoặc phương thức tồn tại có thể được gọi. Điều này cho phép thông tin cần thiết để cấp phát bộ nhớ và "phương thức / chức năng / thủ tục đó có tồn tại không?" được sử dụng khi thực hiện việc biên dịch một đơn vị không cần phải có quyền truy cập vào chính nguồn đó.

Trong Java, trình biên dịch nhận thức được mọi thứ trên đường dẫn lớp của nó và kiểm tra các đối tượng đó để liên kết với chúng (xác minh rằng các phương thức tồn tại, có số lượng đối số phù hợp, v.v ...). Java cũng có thể liên kết động khi tải thời gian chạy trong các lớp khác mà nó không biết gì khi được biên dịch. Xem Class.forName để biết một ví dụ về tải động.

Cả hai tùy chọn đều khá hợp lệ và có những ưu điểm và nhược điểm riêng. Cung cấp một số tệp tiêu đề được xem là cồng kềnh và vi phạm DRY . Mặt khác, nếu bạn không có các thư viện tệp tiêu đề cần phải được kiểm tra bởi trình biên dịch và trình liên kết - một .so hoặc có thể sẽ không có đủ thông tin trong đó để khởi tạo chính xác các đối tượng hoặc xác thực các lệnh gọi phương thức ( và sẽ phụ thuộc vào máy).


0

Thực tế mà nói, với Java, IDE nhìn vào toàn bộ chương trình cùng một lúc; khi ClassB được tham chiếu, trình biên dịch IDE sẽ xem xét nó. Tất cả mọi thứ, bao gồm các thư viện, là một toàn bộ. Khi chương trình đã sẵn sàng, bạn có thể thay đổi đường dẫn lớp, trao đổi vào và ra các tệp. Class riêng lẻ và chuyển đổi các phiên bản thư viện. Bạn cũng có thể biên dịch các tệp .java riêng lẻ mà không cần sử dụng IDE (hoặc bằng cách nào đó tránh việc kiểm tra). Kết quả hoàn toàn không cần nhất quán và nếu không, bạn sẽ nhận được các ngoại lệ trong thời gian chạy. (Một trong nhiều điều mà IDE đang cố gắng thực hiện cho bạn là biến các lỗi thời gian chạy thành thời gian biên dịch, hay đúng hơn là thời gian chỉnh sửa, lỗi.)

C # giống nhau và tôi không nghĩ C và C ++ thực sự khác nhau, theo đó, những gì Java và C # IDE đang làm chỉ là tạo các tiêu đề kiểu C / C ++ cho bạn ở hậu trường.


Trình biên dịch Java cũng biên dịch các công cụ phụ thuộc, nếu cần thiết. Bạn chỉ nhận được ngoại lệ thời gian chạy từ loại điều này nếu bạn thực sự đã rất cố gắng ép buộc mọi thứ (ví dụ: thay đổi và biên dịch lại API sau khi biên dịch cho người tiêu dùng API đó).
Donal Fellows

@DonalFellows: Các vấn đề của tôi đã bị thiếu các thư viện ("Nhưng tôi đã đặt nó trên tất cả các máy của mình!") Và biên dịch lại các chương trình đang chạy (các tệp. Class bị hoán đổi nóng không chủ ý). Tôi có thể thấy trước các gói cập nhật không còn phù hợp với chương trình chính, mặc dù tôi chưa thực hiện được. Tôi đã làm rất nhiều thứ với C và dll (và đã làm nó cho tôi) nhiều năm trước. Tôi tin và hy vọng có rất nhiều sự bảo vệ hiện tại không có ở đó.
RalphChapin

Tôi thực sự không hiểu IDE phải làm gì với cách trình biên dịch / trình liên kết biết cách giải quyết các vấn đề biên dịch / liên kết. Sửa lỗi cho tôi nếu tôi sai, nhưng IDE hoàn toàn trực giao với toàn bộ vấn đề (ngoại trừ việc nó làm giảm bớt nhiệm vụ đối với lập trình viên). Tại sao? Bởi vì trong lý thuyết, IDE sử dụng trình biên dịch trong nền.
Thomas Eding

@ThomasEding: Bạn hoàn toàn đúng. Khi tôi trả lời câu hỏi này, tôi dường như gặp khó khăn khi tách IDE khỏi trình biên dịch / trình liên kết. Lý do của tôi: Java không "liên kết" cho đến khi nó chạy và do đó không thể biết một lệnh gọi lớp hoặc phương thức là sai cho đến lúc đó; IDE không thực sự "làm dịu" nhiệm vụ của tôi, nó làm cho nó có thể. Tôi đã sử dụng (trong FORTRAN và C, từ lâu) để nhận lỗi khi tôi biên dịch, khi tôi liên kết và sau đó khi tôi chạy. Bây giờ tôi nhận được gần như tất cả các lỗi đó ngay khi tôi nhập chúng, điều này làm cho IDE trở thành trình biên dịch, trình liên kết và người thực thi , theo một nghĩa nào đó. Ngày nay, tất cả các lỗi không chạy trong thời gian đến từ IDE.
RalphChapin

0

Ngôn ngữ cũ đôi khi nghiêm ngặt hơn; xem xét những gì có thể có trong Java:

public interface Ifc {
    public static final Ifc MY_CONSTANT = new Implem();
}

public class Implem implements Ifc {
}

Tôi đã thấy các mô hình chống ở trên, và nó thực sự xấu xí (tôi sẽ cấm nó). Cả hai đơn vị biên dịch sử dụng lẫn nhau. Nhưng Ifc có thể được biên dịch thành mã mà không cần Implem biên dịch. Mã được biên dịch,. Class, có thể so sánh với C .obj, chứa "thông tin liên kết:" nhập Implem, gọi hàm tạo không tham số Implem(). Lớp Implem sau đó có thể được biên dịch mà không có vấn đề. Một phần Trình tải lớp - thực hiện khởi tạo / xây dựng dữ liệu lớp JVM và một phần là Máy ảo Java, đóng một vai trò là trình liên kết , tích hợp tất cả.

Ví dụ, biên dịch với một phiên bản của một thư viện cụ thể và chạy với một phiên bản khác của thư viện đó sẽ nhận ra lỗi thời gian chạy.

Vì vậy, câu trả lời: Compilation cung cấp các đơn vị mã đối tượng được biên dịch, cái mà người ta phải xem là mã + dữ liệu + API để liên kết với nhau.

Trình biên dịch sau đó cũng sẽ thực hiện việc đóng gói cùng nhau và xác minh API liên kết; giai đoạn thứ hai.

Điều này có thể gây khó chịu và trông không phù hợp, nhưng bằng chứng toán học có thể hoạt động theo cùng một cách: trong việc chứng minh toàn bộ tính chính xác, người ta có thể đã xem xét một phần để giữ đúng cho đến khi xác minh.

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.