Java promuove una separazione tra le definizioni di classe e le implementazioni, come lo è C ++?

9

Ho un compito a casa e ho bisogno di valutare quale approccio è migliore secondo GRASP "Protected Variation". Ho trovato una domanda su Stack Overflow sulla separazione dell'intestazione e del codice file in C ++ .

Tuttavia, quello che voglio sapere perché Java non segue C ++ nel promuovere la separazione tra le definizioni di classe e le implementazioni di classe. Ci sono dei vantaggi con il metodo Java, rispetto al metodo C ++?

    
posta CoachNono 08.11.2011 - 18:05
fonte

5 risposte

12

Quante linee di codice ci sono nel seguente programma?

#include <iostream>

int main()
{
   std::cout << "Hello, world!\n";
   return 0;
}

Probabilmente hai risposto 7 (o 6 se non hai contato la riga vuota, o 4 se non hai contato le parentesi graffe).

Il tuo compilatore, tuttavia, vede qualcosa di molto diverso:

~$ cpp hello.cpp | wc
  18736   40822  437015

Sì, questo è 18,7 KLOC solo per un "Ciao, mondo!" programma. Il compilatore C ++ deve analizzare tutto ciò. Questo è uno dei motivi principali per cui la compilazione C ++ impiega così tanto tempo rispetto ad altri lingue e il motivo per cui le lingue moderne scansano i file di intestazione.

Una domanda migliore sarebbe

Perché C + + ha file di intestazione?

C ++ è stato progettato per essere un superset di C, quindi ha dovuto mantenere i file di intestazione per la compatibilità all'indietro.

OK, quindi perché C ha i file header?

A causa del suo primitivo modello di compilazione separato. I file oggetto generati dai compilatori C non includono informazioni sui tipi, quindi per evitare errori di tipo è necessario includere queste informazioni nel codice sorgente.

~$ cat sqrtdemo.c 
int main(void)
{
    /* implicit declaration int sqrt(int) */
    double sqrt2 = sqrt(2);
    printf("%f\n", sqrt2);
    return 0;
}

~$ gcc -Wall -ansi -lm -Dsqrt= sqrtdemo.c
sqrtdemo.c: In function ‘main’:
sqrtdemo.c:5:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
sqrtdemo.c:5:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
~$ ./a.out 
2.000000

L'aggiunta delle dichiarazioni di tipo corrette corregge il bug:

~$ cat sqrtdemo.c 
#undef printf
#undef sqrt

int printf(const char*, ...);
double sqrt(double);

int main(void)
{
    double sqrt2 = sqrt(2);
    printf("%f\n", sqrt2);
    return 0;
}

~$ gcc -Wall -ansi -lm sqrtdemo.c
~$ ./a.out 
1.414214

Si noti che non ci sono #include s. Ma quando si utilizza un gran numero di funzioni esterne (la maggior parte dei programmi lo farà), dichiararle manualmente diventa noioso e soggetto a errori. È molto più semplice utilizzare i file di intestazione.

In che modo le lingue moderne sono in grado di evitare i file di intestazione?

Usando un diverso formato di file oggetto che include informazioni sul tipo. Ad esempio, il formato di file * .class Java include " descrittori "che specificano i tipi di campi e i parametri del metodo.

Questa non era una nuova invenzione. In precedenza (1987), quando Borland ha aggiunto "unità" compilate separatamente a Turbo Pascal 4.0, ha scelto di utilizzare un nuovo formato *.TPU anziché il *.OBJ di Turbo C per rimuovere la necessità di file di intestazione.

    
risposta data 09.11.2011 - 09:54
fonte
7

Java ha interfacce per definire un contratto. Ciò fornisce un livello più alto di astrazione rispetto a ciò di cui il chiamante ha bisogno e all'attuazione effettiva. il chiamante non ha bisogno di conoscere la classe di implementazione, ha solo bisogno di conoscere il contratto che supporta.

Supponiamo che tu voglia scrivere un metodo che rallenta tutte le chiavi / valori in una mappa.

public static <K,V> void printMap(Map<K,V> map) {
    for(Entry<K,V> entry: map.entrySet())
        System.out.println(entry);
}

Questo metodo può chiamare entrySet () su un'interfaccia astratta che viene rimossa dalla classe che la implementa. Puoi chiamare questo metodo con.

printMap(new TreeMap());
printMap(new LinkedHashMap());
printMap(new ConcurrentHashMap());
printMap(new ConcurrentSkipListMap());
    
risposta data 08.11.2011 - 19:04
fonte
5

Le intestazioni esistono, francamente, come un incidente storico. È un sistema incredibilmente povero, nessun'altra lingua ha qualcosa di così terribile e chiunque non debba occuparsene dovrebbe rallegrarsi.

    
risposta data 09.11.2011 - 10:01
fonte
3

Le intestazioni sono lì per abilitare la compilazione separata. Con #include le intestazioni, il compilatore non ha bisogno di sapere nulla sulla struttura binaria del codice C ++ compilato e può lasciare quel lavoro a un linker separato. Java non usa un linker separato con il suo compilatore, e poiché i file .class sono rigorosamente definiti, il compilatore è in grado di leggerli per determinare tutti i loro membri con tutti i loro tipi, senza alcuna necessità di re-dichiararli in ogni unità di compilazione.

Puoi includere tutta l'implementazione in un'intestazione C ++, ma fa ricompilare il compilatore ogni volta che è #incluso, forzando il linker a ordinare e scartare le copie duplicate.

    
risposta data 08.11.2011 - 19:42
fonte
0

Java promuove la separazione della definizione e dell'implementazione della classe, dipende solo da dove stai guardando.

Quando sei l'autore di una classe Java, puoi vedere la definizione della classe e la sua implementazione in un unico file. Questo semplifica il processo di sviluppo poiché devi solo andare in un posto per mantenere la classe, non devi passare tra due file (.h e .cpp come faresti in C ++). Tuttavia, quando sei il consumatore della classe ti occupi solo della definizione, tramite un file .class che è impacchettato in una .jar o in una classe .class autonoma

C ++ consente di separare la definizione e l'implementazione, ma è ad-hoc. Ad esempio, non c'è niente che ti impedisca di scrivere il metodo in linea all'interno del file di intestazione, e per le classi template questo è obbligatorio. Il file di intestazione elenca anche tutte le variabili membro, che sono visibili a chiunque guardi il file di intestazione, anche se sono un dettaglio di implementazione della classe e irrilevante per un consumatore.

    
risposta data 09.11.2011 - 10:26
fonte

Leggi altre domande sui tag