So it seems to me that OOP and procedural programming are only different in the way you call a function of an object, but the way you think about a problem and implement its solution is almost the same!
Sì, anche se solo per semplici esempi. OOP offre funzionalità che vanno oltre.
In primo luogo, OOP supporta l'astrazione di un'interfaccia: stuzzicare l'uso e la sua implementazione, accoppiandoli liberamente e quindi supportando la sostituzione.
Questo fornisce il polimorfismo, che consente un certo tipo di riutilizzo del codice: vale a dire, lo stesso client che utilizza un'interfaccia può (assumendo liskov) essere riutilizzato - significativamente e senza modifiche - con diverse implementazioni dell'interfaccia.
Questo è più difficile da fare usando uno stile di programmazione procedurale, poiché l'interfaccia e un'implementazione sono intrinsecamente strettamente accoppiate. È necessario qualcosa in più per aiutarli a disaccoppiarli, e questo includerebbe alcune tecniche OOP.
In secondo luogo, l'eredità di OOP è un meccanismo per il riutilizzo del codice di implementazione. I metodi della classe base possono essere riutilizzati specializzando le sottoclassi. (Tieni comunque presente la raccomandazione per la composizione sull'ereditarietà.)
E questi due: separazione dell'interfaccia dall'implementazione e l'ereditarietà del codice, possono lavorare insieme: una sottoclasse specializzata in grado di riutilizzare parte dell'implementazione delle classi base e il consumo del codice client può essere riutilizzato non modificato con quella sub specializzata classe.
Se scriviamo codice come questo:
Car car = new Car(); // Car is a class here
car.moveForward();
in sole due righe di codice, stiamo confondendo due ruoli diversi. Il ruolo giocato dalla seconda riga di codice è quello di un client che consuma un'interfaccia, mentre il ruolo giocato dalla prima riga di codice è quello di decisore, iniettore, fabbrica o configuratore. Spesso, vorremmo separare questi ruoli, in diversi moduli. Pertanto, la macchina potrebbe essere creata in un modulo e utilizzata da un'altra.
OOP incoraggia questa separazione, con l'aspettativa che (quando fatto correttamente) il modulo client consumante possa eseguire su molteplici potenziali implementazioni.
Struct vs. Class è una distinzione che dipende dalla lingua che stai utilizzando.
C, ovviamente, non ha classi; struct's ha una semantica a valore finché non si usano i puntatori. Una volta che usi i puntatori, puoi applicare alcune tecniche OOP.
In C ++ non c'è praticamente alcuna differenza tra struct e class (il default del modificatore di accesso è diverso, public per struct, private per le classi).
C # ha sia structs che classi in cui il primo ha semantica di valore e la seconda semantica di riferimento (ad es. variabili locali e parametri può essere e può fa riferimento agli oggetti, sebbene non possa essere oggetti).
Le classi di Java e C # sono simili; Java non ha strutture: i suoi unici tipi di valore sono le primitive (ad es. Int).
Quindi, in C #, ad esempio, supponendo che Car
sia una classe, Car car;
crea una variabile di riferimento che può riferirsi a un oggetto che è di tipo Car
, sebbene anche qualsiasi sottoclasse di Car
. Mentre se Car
è una struct, allora quella stessa dichiarazione crea una struct di tipo Car
.