In che modo i compilatori conoscono le altre classi e le loro proprietà?

14

Sto scrivendo il mio primo linguaggio di programmazione che è orientato agli oggetti e finora è così bello creare una singola 'classe'. Ma diciamo che voglio avere classi, diciamo ClassA e ClassB . A condizione che questi due non abbiano nulla a che fare l'uno con l'altro, tutto va bene. Tuttavia, diciamo che ClassA crea un ClassB - questo pone 2 domande correlate:

-Come fa il compilatore a sapere quando compila ClassA che esiste anche ClassB e, se lo fa, come fa a sapere che sono proprietà?

I miei pensieri fino ad ora erano stati: invece di compilare ogni classe alla volta (ad esempio, scansionare, analizzare e generare codice) ogni "file (non proprio file, di per sé, ma una" classe ") ho bisogno di scansionare + analizzare prima ciascuno, quindi generare il codice per tutti?

    
posta OnResolve 27.06.2012 - 23:02
fonte

3 risposte

13

Diverse lingue (e quindi compilatori) si avvicinano 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 usato quando si effettua la compilazione di una singola unità che non ha bisogno di accedere alla sorgente stessa.

In Java, il compilatore è a conoscenza di cose sul suo classpath e ispeziona quegli oggetti per collegarsi a loro (verificando che i metodi esistano, abbiano il giusto numero di argomenti, ecc ...). Java può anche collegarsi dinamicamente al caricamento in runtime in altre classi di cui non sa nulla quando è stato compilato. Vedi Class.forome per un esempio di caricamento dinamico.

Entrambe le opzioni sono abbastanza valide e presentano una serie di vantaggi e svantaggi. Fornire i file di intestazione alcuni vedono come ingombrante e violento ASCIUGA . D'altra parte, se non si dispone di librerie di file di intestazione devono essere ispezionabili dal compilatore e dal linker - un file .so o .dll probabilmente non avrà abbastanza informazioni in esso per creare un'istanza appropriata degli oggetti o convalidare le chiamate al metodo ( e sarebbe dipendente dalla macchina).

    
risposta data 27.06.2012 - 23:18
fonte
0

In pratica, con Java, gli IDE guardano un intero programma contemporaneamente; quando si fa riferimento a ClassB, il compilatore IDE lo esaminerà. Tutto, incluse le librerie, è un intero completo. Una volta che il programma è pronto, è possibile modificare i percorsi di classe, scambiare i singoli file .class e cambiare le versioni di libreria. È anche possibile compilare singoli file .java senza utilizzare l'IDE (o in qualche modo evitare i suoi controlli). Il risultato non deve necessariamente essere coerente e, in caso contrario, otterrà eccezioni run-time. (Una delle molte cose che un IDE sta cercando di fare per te è trasformare gli errori di runtime in errori in fase di compilazione, o meglio di modifica, in tempo.)

C # è circa lo stesso, e non credo che C e C ++ siano davvero così diversi, in quanto ciò che stanno facendo gli IDE di Java e C # è solo la creazione di intestazioni di stile C / C ++ per te dietro le quinte.

    
risposta data 28.06.2012 - 16:25
fonte
0

Le lingue precedenti a volte sono più rigide; considera ciò che è possibile in Java:

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

public class Implem implements Ifc {
}

Ho visto l'anti-pattern sopra, ed è veramente brutto (lo avrei proibito). Entrambe le unità di compilazione si usano l'una con l'altra. Ma Ifc può essere compilato per codice senza avere una Implem compilata. Il codice compilato, .class, paragonabile a C .obj, contiene "informazioni sul collegamento:" un'importazione di Implem, chiamando un costruttore parametrico Implem() . La classe Implem può quindi essere compilata senza problemi. In parte ClassLoader - facendo i dati della classe JVM di inizializzazione / build, e in parte la Java Virtual Machine stessa, 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 riconoscerà gli errori di runtime.

Quindi la risposta: La compilazione fornisce unità di codice oggetto compilato, che deve essere visto come codice + dati + API per il collegamento tra loro.

Il compilatore dovrebbe in seguito fare anche un pacchettizzare insieme e verificare l'API di collegamento; una seconda fase.

Ciò potrebbe irritare e apparire poco elegante, ma le dimostrazioni matematiche possono operare nello stesso modo: nel provare l'intera correttezza, si può già considerare una parte da tenere valida fino alla verifica.

    
risposta data 24.03.2014 - 23:35
fonte

Leggi altre domande sui tag