Come fanno i compilatori a conoscere altre classi e le loro proprietà?


14

Sto scrivendo il mio primo linguaggio di programmazione che è orientato agli oggetti e finora così buono con la creazione di una singola "classe". Ma diciamo che voglio frequentare le lezioni, dire ClassAe ClassB. A condizione che questi due non abbiano nulla a che fare l'uno con l'altro, allora tutto va bene. Tuttavia, dire ClassAcrea un - ClassBquesto pone 2 domande correlate:

-Come saprebbe il compilatore durante la compilazione ClassAche ClassBesiste anche, e, se lo fa, come fa a sapere che sono le proprietà?

I miei pensieri finora erano stati: invece di compilare ogni classe alla volta (cioè scansionare, analizzare e generare codice) ogni "file (non proprio file, di per sé, ma una" classe ") devo scansionare + analizzare prima , quindi generare codice per tutti?

Risposte:


13

Lingue diverse (e quindi compilatori) lo affrontano in modo diverso.

Nella famiglia C, i diversi moduli hanno un file di intestazione corrispondente che viene utilizzato durante la creazione dell'oggetto. I file di intestazione forniscono informazioni sulla dimensione dell'oggetto e su quali funzioni o metodi possono essere invocati. Ciò consente le informazioni necessarie per l'allocazione della memoria e "esiste quel metodo / funzione / procedura?" viene utilizzato quando si esegue la compilazione di una singola unità che non ha bisogno di avere accesso alla fonte stessa.

In Java, il compilatore è a conoscenza delle cose sul suo percorso di classe e ispeziona quegli oggetti per collegarsi contro di essi (verificando che i metodi esistano, abbiano il giusto numero di argomenti, ecc ...). Java può anche collegarsi dinamicamente al caricamento del runtime in altre classi di cui non sa nulla al momento della compilazione. Vedi Class.forName per un esempio di caricamento dinamico.

Entrambe le opzioni sono abbastanza valide e presentano una serie di vantaggi e svantaggi. Fornire file di intestazione che alcuni vedono come ingombranti e violanti DRY . D'altra parte, se non si dispone di file di intestazione, le librerie devono essere ispezionabili dal compilatore e dal linker: è probabile che un .so o .dll non disponga di informazioni sufficienti per istanziare correttamente gli oggetti o convalidare le chiamate al metodo ( e dipende dalla macchina).


0

In pratica, con Java, l'IDE guarda contemporaneamente un intero programma; quando si fa riferimento a ClassB, il compilatore IDE lo esaminerà. Tutto, comprese le biblioteche, è un tutto completo. Una volta che il programma è pronto, è possibile modificare i percorsi di classe, scambiare e rimuovere singoli file .class e cambiare la versione della libreria. Puoi anche compilare singoli file .java senza usare l'IDE (o in qualche modo evitando i suoi controlli). Il risultato non ha bisogno di essere coerenti a tutti, e se non lo è si verrà ottenere run-time eccezioni. (Una delle molte cose che un IDE sta cercando di fare per te è trasformare gli errori di runtime in errori di compilazione, o meglio, di modifica dei tempi.)

C # è più o meno lo stesso, e non penso che C e C ++ siano davvero così diversi, in quanto ciò che fanno gli IDE Java e C # è semplicemente creare intestazioni in stile C / C ++ per te dietro le quinte.


I compilatori Java compilano anche cose dipendenti, se necessario. Otterrai eccezioni di runtime da questo genere di cose solo se hai davvero cercato di forzare le cose (ad esempio, cambiando e ricompilando un'API dopo aver compilato i consumatori di quell'API).
Donal Fellows,

@DonalFellows: I miei problemi sono mancati le librerie ("Ma l'ho messo su tutti i miei computer!") E ricompilando i programmi in esecuzione (file .class involontariamente hot-swap). Posso prevedere l'aggiornamento dei pacchetti che non corrispondono più al programma principale, anche se non l'ho ancora fatto. Ho fatto molto con C e .dll (e me l'avevo fatto) anni fa. Credo e spero che ci siano molte protezioni in atto ora che non c'erano allora.
RalphChapin,

Davvero non capisco cosa abbia a che fare un IDE con il modo in cui un compilatore / linker sa come risolvere i problemi di compilazione / linker. Correggimi se sbaglio, ma un IDE è totalmente ortogonale all'intero problema (tranne per il fatto che facilita l'attività sul programmatore). Perché? Perché in teoria l'IDE utilizza il compilatore in background.
Thomas Eding,

@ThomasEding: hai perfettamente ragione. Quando ho risposto a questa domanda, sembrava che avessi problemi a separare l'IDE dal compilatore / linker. La mia scusa: Java non "collega" fino a quando non viene eseguito e quindi non è possibile sapere che un riferimento di classe o una chiamata di metodo è errata fino ad allora; l'IDE non "facilita" il mio compito, lo rende possibile. Ho usato (in FORTRAN e C, molto tempo fa) per ottenere errori durante la compilazione, quando mi collegavo e poi quando correvo. Ora ottengo quasi tutti quegli errori nel momento in cui li scrivo, il che rende l'IDE un compilatore, linker ed esecutore, in un certo senso. Oggi, tutti gli errori non di runtime provengono dall'IDE.
RalphChapin,

0

Le lingue più vecchie a volte sono più rigorose; considera cosa è possibile in Java:

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

public class Implem implements Ifc {
}

Ho visto l'anti-schema sopra, ed è davvero brutto (lo avrei proibito). Entrambe le unità di compilazione si usano a vicenda. Ma Ifc può essere compilato per codificare senza avere un Implem compilato. Il codice compilato, .class, paragonabile a un C .obj, contiene "informazioni sul collegamento:" un'importazione di Implem, che chiama un costruttore senza parametri Implem(). La classe Implem può quindi essere compilata senza problemi. In parte ClassLoader - facendo l'inizializzazione / compilando i dati di classe JVM, e in parte la stessa Java Virtual Machine, gioca un po 'come linker , integrando tutto.

Ad esempio, la compilazione con una versione di una libreria specifica e l'esecuzione con un'altra versione di quella libreria riconosceranno errori di runtime.

Quindi la risposta: la compilazione fornisce unità di codice oggetto compilato, che si deve vedere come codice + dati + API per il collegamento insieme.

Successivamente il compilatore dovrebbe anche fare un impacchettamento e verificare l'API di collegamento; una seconda fase.

Ciò potrebbe irritare e apparire ininfluente, ma le prove matematiche possono funzionare allo stesso modo: nel dimostrare l'intera correttezza si può già considerare una parte valida fino alla verifica.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.