2014-12-05 16 views

risposta

13

Prima di tutto, non ascoltare nessuno che dice "non c'è orientamento all'oggetto nel linguaggio x" perché non hanno veramente capito che OO è un metodo di progettazione , completamente separato dalla sintassi della lingua.

Alcune lingue hanno modi eleganti per implementare OO, altri no. Eppure è possibile scrivere un programma orientato agli oggetti in qualsiasi lingua, for example in C. Allo stesso modo, il tuo programma non otterrà automaticamente un design OO corretto solo perché lo hai scritto in Java o perché hai usato determinate parole chiave della lingua.

Il modo in cui si sceglie di implementare l'incapsulamento privata in C è un po 'più cruda che in lingue con supporto OO, ma lo fa in questo modo:

// module.h

void set_x (int n); 
int get_x (void); 

// modulo. c

static int x; // private variable 

void set_x (int n) 
{ 
    x = n; 
} 

int get_x (void) 
{ 
    return x; 
} 

// main.c

#include "module.h" 

int main (void) 
{ 
    set_x(5); 
    printf("%d", get_x()); 
} 

Può chiamarlo "classe" o "ADT" o "modulo codice" come preferisci.

Questo è il modo in cui ogni ragionevole programma C è scritto. Ed è stato scritto negli ultimi 30-40 anni circa, a patto che il design del programma sia esistito. Se dici che non ci sono setter/getter in un programma C, allora è perché non hai esperienza dell'uso di C.

+0

Sì, questo è esattamente ciò che cerco di capire: questi approcci (variabile statica + 'getter in stile C' e semplice 'variabile + dichiarazione extern') sono assolutamente sostituibili, o uno è ancora preferibile? – elusive

+0

@giorgim Uguale, anche se il tipo di variabile deve essere esposto al chiamante, è necessario implementarlo tramite il tipo incompleto ("opaco"), come menzionato in un'altra risposta. – Lundin

+1

@giorgim [Ecco un esempio] (http://stackoverflow.com/questions/15408921/how-to-create-a-new-object-in-ac-function-and-pass-a-reference-to- it/15409254 # 15409254) e [qui un altro] (http://stackoverflow.com/questions/12702703/initializing-a-struct-of-a-struct/12704566#12704566). – Lundin

9

Sì, è molto possibile ea volte anche utile. C supporta opache tipi: codice

struct Context; 

C compilati solo con questa dichiarazione portata non può accedere alcun membro ipotetiche della struct, e non possono utilizzare valore di tipo Context entrambi. Ma può ancora gestire puntatori aContext valori, per cui funzioni come questi sono possibili:

Context *make_context(...); 
int context_get_foo(Context *); 
void context_set_foo(Context *, int); 

Questo pattern isola il codice client C da eventuali modifiche alle dimensioni o disposizione interna Context. Si noti che questa è una garanzia più forte del semplice dichiarare ma non documentare i membri: anche se i programmatori ignorano debitamente i membri non documentati, l'uso di valore della struct è consentito (e sicuramente lo farà scivolare), e ora il codice deve essere ricompilato quando cambia la dimensione. In altre parole, i tipi opachi gestiti solo attraverso i puntatori offrono una maggiore stabilità dell'ABI.

+0

Il tipo opaco è un ottimo modo per implementare il vero incapsulamento privato delle strutture ed è sicuramente la strada da percorrere per programmatori C professionisti. Ma il tipo opaco non è necessario solo per dichiarare alcune variabili private e implementare setter/getter per loro, vedere la mia risposta per un modo semplificato di farlo. – Lundin

+0

@Lundin Ciò che descrivi funziona anche, è in effetti più semplice e potrebbe anche essere più vicino a ciò che l'OP chiedeva (dato che menzionavano 'extern'). Ma non lo chiamerei un "modo semplificato" perché è uno strumento abbastanza diverso, allo stesso modo in cui i membri 'static' in Java non sono membri di istanza" semplificati ". – delnan

+0

È ragionevole dire ora che SE NON ASSOLUTAMENTE non ho bisogno di strutture opache in un progetto, dovrei usare "variabili statiche + getter" per avere uno stile profetico, oppure è indifferente se usare questo o solo l'accesso diretto da altri moduli con 'dichiarazione extern'? – elusive