Qual è il vantaggio della programmazione orientata agli oggetti rispetto alla programmazione procedurale?

76

Sto cercando di capire la differenza tra linguaggi procedurali come C e linguaggi orientati agli oggetti come C ++. Non ho mai usato il C ++, ma ho discusso con i miei amici su come differenziare i due.

Mi è stato detto che C ++ ha concetti orientati agli oggetti così come modalità pubbliche e private per la definizione di variabili: cose che C non ha. Non ho mai dovuto usare questi durante lo sviluppo di programmi in Visual Basic.NET: quali sono i vantaggi di questi?

Mi è stato anche detto che se una variabile è pubblica, è accessibile ovunque, ma non è chiaro come sia diversa da una variabile globale in una lingua come C. Inoltre non è chiaro in che modo una variabile privata differisce da una variabile locale.

Un'altra cosa che ho sentito è che, per ragioni di sicurezza, se è necessario accedere a una funzione, questa dovrebbe essere ereditata per prima. Il caso d'uso è che un amministratore dovrebbe avere solo tutti i diritti di cui ha bisogno e non tutto, ma sembra che anche un condizionale funzionerebbe:

if ( login == "admin") {
    // invoke the function
}

Perché non è l'ideale?

Dato che sembra esserci un modo procedurale per fare tutto orientato agli oggetti, perché dovrei preoccuparmi della programmazione orientata agli oggetti?

    
posta niko 16.11.2011 - 06:20
fonte

12 risposte

133

Tutte le risposte finora si sono concentrate sull'argomento della tua domanda come affermato, che è "qual è la differenza tra c e c ++". In realtà, sembra che tu sappia qual è la differenza, semplicemente non capisci perché hai bisogno di quella differenza. Quindi, altre risposte hanno tentato di spiegare OO e incapsulamento.

Volevo inserire un'altra risposta, perché in base ai dettagli della tua domanda, credo che sia necessario fare diversi passi indietro.

Non capisci lo scopo di C ++ o OO, perché a te sembra che l'applicazione abbia semplicemente bisogno di memorizzare i dati. Questi dati sono memorizzati in variabili. "Perché dovrei rendere inaccessibile una variabile? Ora non posso più accedervi! Rendendo tutto pubblico, o meglio ancora globale, posso leggere i dati da qualsiasi luogo e non ci sono problemi." - E hai ragione, sulla base della scala dei progetti che stai attualmente scrivendo, probabilmente non ci sono molti problemi (o ci sono, ma non li hai ancora conosciuti).

Penso che la domanda fondamentale a cui devi veramente rispondere sia: "Perché mai dovrei nascondere i dati? Se lo faccio, non posso lavorarci!" E questo è il motivo:

Diciamo che inizi un nuovo progetto, apri il tuo editor di testo e inizi a scrivere funzioni. Ogni volta che è necessario memorizzare qualcosa (per ricordarlo per dopo), si crea una variabile. Per semplificare le cose, rendi globali le tue variabili. La tua prima versione della tua app funziona alla grande. Ora inizi ad aggiungere più funzionalità. Hai più funzioni, alcuni dati che hai memorizzato da prima devono essere letti dal tuo nuovo codice. Altre variabili devono essere modificate. Continui a scrivere più funzioni. Ciò che potresti aver notato (o, in caso contrario, noterai assolutamente in futuro) è che, man mano che il tuo codice si ingrandisce, ti occorrerà sempre più tempo per aggiungere la funzione successiva. E man mano che il tuo codice diventa più grande, diventa sempre più difficile aggiungere funzionalità senza rompere qualcosa che prima funzionava. Perché? Perché devi ricordare quali tutte le tue variabili globali stanno memorizzando e devi ricordare dove tutti sono in corso di modifica. E devi ricordare quale funzione è accettabile per chiamare quale esatto ordine e se li chiami in un diverso ordine, potresti ottenere errori perché le tue variabili globali non sono abbastanza valido ancora. Ti sei mai imbattuto in questo?

Quanto sono grandi i tuoi progetti tipici (linee di codice)? Ora immagina un progetto da 5000 a 50000 volte più grande del tuo. Inoltre, ci sono più persone che ci lavorano. In che modo tutti nel team possono ricordare (o persino essere consapevoli) di ciò che stanno facendo tutte quelle variabili?

Quello che ho descritto sopra è un esempio di codice perfettamente accoppiato. E sin dall'alba dei tempi (ipotizzando che il tempo inizi il 1 ° gennaio 1970), il genere umano ha cercato modi per evitare questi problemi. Il modo in cui li eviti è suddividendo il tuo codice in sistemi, sottosistemi e componenti e limitando il numero di funzioni che hanno accesso a qualsiasi parte di dati. Se ho 5 interi e una stringa che rappresenta un qualche tipo di stato, sarebbe più facile per me lavorare con questo stato se solo 5 funzioni impostano / ottengono i valori? o se 100 funzioni impostano / ottengono questi stessi valori? Anche senza i linguaggi OO (ad esempio C), le persone hanno lavorato duramente per isolare i dati da altri dati e creare netti confini di separazione tra diverse parti del codice. Quando il progetto raggiunge una certa dimensione, la facilità di programmazione diventa "posso accedere alla variabile X dalla funzione Y", ma "come faccio a garantire SOLO le funzioni A, B, C e nessun altro tocca la variabile X".

Questo è il motivo per cui sono stati introdotti concetti OO ed è per questo che sono così potenti. Ti permettono di nascondere i tuoi dati da te e tu vuoi a farlo apposta, perché meno codice che vede quei dati, meno possibilità ci sono, che quando aggiungi la prossima funzione, lo farai rompere qualcosa. Questo è lo scopo principale dei concetti di incapsulamento e programmazione OO. Permettono di rompere i nostri sistemi / sottosistemi in scatole ancora più granulari, fino al punto in cui, indipendentemente da quanto sia grande il progetto complessivo, un determinato insieme di variabili può essere raggiunto solo da 50-200 righe di codice e il gioco è fatto! Ovviamente c'è molto di più nella programmazione OO, ma, in sostanza, questo è il motivo per cui C ++ ti offre le opzioni per dichiarare dati / funzioni come privati, protetti o pubblici.

La seconda idea più grande in OO è il concetto di livelli di astrazione. Sebbene i linguaggi procedurali possano anche avere astrazioni, in C, un programmatore deve fare uno sforzo cosciente per creare tali livelli, ma in C ++, quando si dichiara una classe, si crea automaticamente un livello di astrazione (dipende comunque da te se questa astrazione o meno aggiungerà o rimuoverà il valore). Dovresti leggere / ricercare di più sui livelli di astrazione e se hai altre domande, sono certo che questo forum sarà più che felice di rispondere anche a quelle.

    
risposta data 16.11.2011 - 09:05
fonte
10

Hmm ... forse è meglio fare il backup e provare a dare un'idea dell'intenzione di base della programmazione orientata agli oggetti. Gran parte dell'intento della programmazione orientata agli oggetti è di consentire la creazione di tipi di dati astratti. Per un esempio davvero semplice con il quale sei indubbiamente familiare, considera una stringa. Una stringa avrà in genere un buffer per contenere il contenuto della stringa, alcune funzioni che possono operare sulla stringa (cercare in essa, accedere a parti di esso, creare sottostringhe, ecc.) Inoltre avrà (almeno in genere) qualcosa da tenere traccia della lunghezza (corrente) della stringa e (probabilmente) della dimensione del buffer, quindi se (ad esempio) si aumenta la dimensione della stringa da 1 a 1000000, si saprà quando è necessario più memoria per contenere il più grande contenuti.

Quelle variabili (il buffer, la lunghezza corrente e la dimensione del buffer) sono private della stringa stessa, ma sono non locali per una particolare funzione. Ogni stringa ha contenuti di una certa lunghezza, quindi dobbiamo tenere traccia di quel contenuto / lunghezza per quella stringa. Al contrario, la stessa funzione (ad es. Per estrarre una sottostringa) potrebbe operare su più stringhe diverse in momenti diversi, in modo che i dati non possano essere locali rispetto alla singola funzione.

Pertanto, otteniamo alcuni dati privati della stringa, quindi è solo (direttamente) accessibile alle funzioni stringa. Il mondo esterno può ottenere la lunghezza della stringa usando una funzione di stringa, ma non ha bisogno di sapere nulla sull'interno della stringa per ottenerla. Allo stesso modo, potrebbe modificare la stringa - ma, di nuovo, lo fa tramite le funzioni di stringa, e solo loro modificano direttamente quelle variabili localmente all'oggetto stringa.

Per quanto riguarda la sicurezza, noterei che mentre ciò è ragionevole come un'analogia, è non come le cose funzionano davvero. In particolare, l'accesso in C ++ è specificamente non destinato a soddisfare lo stesso tipo di requisiti dell'accesso in un sistema operativo. Si suppone che un sistema operativo imponga le restrizioni così (per esempio) un utente normale non può fare cose riservate per un amministratore. Al contrario, il controllo degli accessi in C ++ ha il solo scopo di prevenire incidenti . In base alla progettazione, chiunque voglia può ignorarli abbastanza facilmente. Sono sullo stesso ordine di marcatura di un file di sola lettura in modo da non eliminarlo accidentalmente. Se decidi di eliminare il file, è banale cambiarlo da read-only a read-write; tutto ciò che si imposta in sola lettura è farvi almeno pensarci un secondo e decidere di eliminare il file in modo che non venga cancellato accidentalmente solo dal tasto sbagliato al momento sbagliato .

    
risposta data 16.11.2011 - 07:17
fonte
6

OOP contro C non riguarda davvero nessuna delle cose che hai discusso. Si tratta principalmente del codice di imballaggio in aree che non possono / non possono involontariamente (o talvolta anche intenzionalmente) influenzarsi a vicenda.

C ti consente di eseguire praticamente qualsiasi funzione da qualsiasi luogo. OOP lo impedisce raggruppando i metodi in classi e consentendo solo di utilizzare i metodi facendo riferimento alla classe che li contiene. Quindi, un potenziale vantaggio di OOP è che è molto più probabile avere una migliore disposizione del codice senza molta esperienza per dirti che dovresti.

    
risposta data 16.11.2011 - 07:18
fonte
4

Una classe ben scritta dovrebbe essere una piccola "isola di fiducia": puoi usarla e supporre che faccia "la cosa giusta" e che ti protegga dalle insidie più comuni. Ciò rende una buona classe un elemento fondamentale, che è molto più riutilizzabile come un mucchio di funzioni e variabili, che potrebbero funzionare bene ma mostrarti tutto il loro orribile coraggio, e costringerti a capire come funzionano insieme, come devono essere inizializzati ecc. Una buona classe dovrebbe essere come una spina USB, mentre la soluzione procedurale è come un mucchio di fili, chip, stagno e un po 'di saldante.

Un punto che non è stato discusso in profondità è l'aspetto dell'interfaccia / implementazione. Un'interfaccia descrive il comportamento, ma non la realizzazione. Quindi un'interfaccia di lista descrive il concetto di un elenco e il suo comportamento: ci si aspetterebbe cose come i metodi add, remove e size. Ora ci sono molti modi diversi per implementare questo elenco, ad es. come elenco collegato o utilizzando un buffer di array. La potenza della programmazione OO è che utilizzando un'interfaccia è possibile ragionare sul comportamento senza conoscere l'implementazione. L'accesso a variabili o metodi interni distruggerebbe questa astrazione, non è possibile sostituire un'implementazione di elenco con un'altra e non è possibile migliorare un'implementazione esistente senza toccare il codice utilizzando la classe. Questo è uno dei motivi principali per cui sono necessarie variabili e metodi privati: per proteggere i dettagli interni dell'implementazione, quindi l'astrazione rimane intatta.

OO fa anche un ulteriore passo avanti: E.g. per le librerie è possibile definire un'interfaccia per le cose che nemmeno esistono ancora e scrivere codice che funzioni con quell'interfaccia. Gli utenti possono scrivere classi implementando l'interfaccia e utilizzare i servizi forniti dalla libreria. Ciò consente un grado di flessibilità che non è possibile con la programmazione procedurale.

    
risposta data 18.11.2011 - 10:01
fonte
3

C'è un modo per fare tutto con una macchina di Turing, o almeno in un linguaggio assembly per il codice macchina a cui un programma C o C ++ verrà eventualmente compilato.

Quindi la differenza non riguarda ciò che il codice può fare, ma ciò che le persone possono fare.

Le persone commettono errori. I lotti.

OOP introduce un paradigma e una sintassi che aiutano a ridurre le dimensioni e la densità di probabilità dello spazio di possibili errori di codifica umana. A volte rendendo illegale l'errore per una determinata classe di oggetto dati (ad esempio non è un metodo dichiarato per quell'oggetto). A volte, facendo l'errore più verboso, o stilisticamente strano rispetto all'uso canonico del linguaggio. A volte richiedendo un'interfaccia con usi meno inconsistenti o impigliati (pubblico vs privato). ecc.

Più grande è il progetto, maggiore è la probabilità di errori. A quale nuovo coder potrebbe non essere esposto se solo sperimentato con piccoli programmi. Quindi la potenziale perplessità sul perché OOP è prezioso.

    
risposta data 16.11.2011 - 20:22
fonte
2

La tua domanda sembra più sullo scopo di OOP piuttosto che sulla differenza. Il concetto nel tuo post è Incapsulamento; e l'incapsulamento esiste per supportare CHANGE. Quando altre classi accedono ai tuoi interni diventa difficile modificarle senza romperle. In OOP fornisci un'interfaccia (membri pubblici) attraverso cui permetti ad altre classi di interagire con la tua e nascondi i tuoi interni in modo che possano essere tranquillamente cambiati.

    
risposta data 16.11.2011 - 08:26
fonte
2

No matter where I read private variables cannot be accessed whereas public variables can be then why not make public as global and private as local whats the difference? whats the real use of public and private ? please dont say it can be used by everyone, I suppose why not we use some conditions and make the calls ?

Spero che tu non voglia mai più di una stringa nella tua applicazione. Spero anche che le variabili locali persistano tra le chiamate di funzione. Queste cose potrebbero essere le stesse in termini di accessibilità, ma in termini di durata e altri usi? Non sono assolutamente uguali.

    
risposta data 16.11.2011 - 08:30
fonte
1

Come molti hanno detto che qualsiasi programma, una volta compilato, viene trasformato in un codice binario e, poiché una stringa binaria può essere usata per rappresentare un intero, qualsiasi programma è alla fine solo un numero. Tuttavia, definire il numero necessario potrebbe essere piuttosto difficile ed è per questo che sono venuti fuori i linguaggi di programmazione di alto livello. I linguaggi di programmazione sono solo modelli del codice assembly che alla fine producono. Vorrei spiegarti la differenza tra la programmazione procedurale e OO per mezzo di questo bellissimo articolo sulla programmazione orientata al contesto link

Come potete vedere da questa immagine, rappresentata nel documento, la programmazione procedurale fornisce solo una dimensione per associare un'unità computazionale con un nome. Qui, chiamate o nomi di procedure vengono direttamente associati alle implementazioni della procedura. Nella figura, una chiamata m1 non lascia altra scelta che l'invocazione della sola implementazione della procedura m1.

La programmazione orientata agli oggetti aggiunge un'altra dimensione per la risoluzione dei nomi a quella della programmazione procedurale. Oltre al metodo o al nome della procedura, l'invio dei messaggi tiene conto del ricevitore del messaggio quando si cerca un metodo. Nella Figura b vediamo due implementazioni del metodo m1. La scelta del metodo appropriato dipende non solo dal nome del messaggio m1, ma anche dal destinatario del messaggio reale, qui Ry.

Questo consente effettivamente l'incapsulamento e la modularizzazione.

La figura-c è finalmente basata sulla programmazione orientata agli oggetti estende il dispacciamento del metodo orientato agli oggetti da un'altra dimensione.

Spero che questo ti abbia aiutato a pensare a OOP da una prospettiva diversa.

    
risposta data 16.11.2011 - 22:28
fonte
0

(+ 1) Fare una domanda su qualcosa che non capisci, è buono, anche se sembra sciocco.

La differenza è Object & Programmazione orientata alla classe. "Plain C", funziona con dati e amp; funzioni. "C ++" aggiunge concetti di "oggetti e classi", oltre a diversi concetti secondari correlati.

Tuttavia, sostengo gli sviluppatori per imparare "Plain C" prima di "C ++". O "Pascal procedurale" prima di "Object Pascal".

Molti sviluppatori pensano che gli studenti dovrebbero insegnare solo una roba.

Ad esempio, i vecchi insegnanti che non ottengono O.O. e insegnano solo "Plain Structured C".

O insegnanti "hipster" che insegnano solo O.O., ma non "Plain C", perché "non ne hai bisogno". O entrambi, senza preoccuparsi dell'ordine di insegnamento.

Penso piuttosto che agli studenti dovrebbero essere insegnati sia "Structured Plain C" che "Object Oriented C (C ++)". Con "Plain C", prima, e "C ++", più tardi.

Nel mondo reale, devi imparare entrambi i paradigmi (più altri paradigmi, come "funzionale").

Pensare a programmi strutturati come un grande "oggetto" singolare può essere d'aiuto.

Dovresti anche porre l'accento sui namespace ("moduli"), in entrambe le lingue, molti insegnanti lo ignorano, ma è importante.

    
risposta data 16.11.2011 - 18:51
fonte
0

In una parola, gestione del progetto. Quello che voglio dire è che C ++ mi aiuta a far rispettare le regole su come il mio codice viene usato da altri. Lavorando su un progetto di 5,5 milioni di linee trovo molto utile la programmazione orientata agli oggetti. Un altro vantaggio è il compilatore che fa sì che io (e tutti gli altri) segua determinate regole e catturi errori minori in fase di compilazione. Ci sono anche tutti i vantaggi teorici, ma volevo solo concentrarmi sulle cose pratiche quotidiane. Dopo tutto, viene compilato in codice macchina.

    
risposta data 18.11.2011 - 07:34
fonte
-1

La programmazione orientata agli oggetti è la programmazione procedurale, con caselle.

In PP, hai una casella, uno stato, che diventa incredibilmente grande man mano che il progetto cresce, causando la comparsa di effetti collaterali ogni volta che dimentichi un piccolo bit di quello stato di grandi dimensioni.

In OO ci sono molte caselle, molti stati e man mano che il progetto cresce, le scatole crescono un po 'e il numero di scatole cresce molto.

Resta più facile guardare scatole più piccole, facile avere l'illusione di un'immagine intera, ma in realtà quasi impossibile, poiché guardare le classi e le interfacce nasconde i dettagli di implementazione che possono avere importanti ramificazioni.

Nella programmazione funzionale, hai molte caselle funzione e decidi che ogni funzione ha una voce (parametri) e una uscita (ritorna), con rigorosamente nessun altro accesso al contesto esterno.

Poiché non esiste uno stato né effetti collaterali (in base alla progettazione), puoi tranquillamente analizzare qualsiasi funzione separatamente dall'intero e sapere al 100% come si comporterà in qualsiasi circostanza.

Dato che sei un codice di boxing per unità logiche che rappresentano azioni, diventa anche possibile avere una sola casella per ogni azione tipica.

Questo ridurrà il codice di qualsiasi progetto su larga scala di un fattore enorme rispetto a OOP che promuove l'occultamento di più funzioni analogiche su tutto il codice in diverse classi.

Questo supererà anche il PP di molto perché è possibile far crescere il progetto molto più a lungo poiché non ci sono più stati XXXXXXXL da tenere traccia di.

In sintesi, il PP è probabilmente il modo più semplice per accedere a un programma semplice e FP è probabilmente il modo più semplice per avvicinarsi a un programma complesso.

Se prendi in considerazione l'obiettivo di unificare tutte le basi di codice e di migliorare il riutilizzo del codice, FP dovrebbe sempre essere usato, in quanto è l'unico paradigma che ha senso su larga scala, nonché l'unico paradigma che ha la riusabilità al 100% (puoi semplicemente copiare incolla una funzione e usarla da qualche altra parte, senza alcun tipo di sovraccarico).

E ottieni un test dell'unità affidabile al 100% gratuitamente.

E non devi scrivere "private static final of_doom genius awesome string_1".

E ottieni il parallelismo gratuitamente.

    
risposta data 28.09.2013 - 09:22
fonte
-3

La semplice differenza di una frase è che C ++ è C con Classi. (anche se ora è molto più) Non so perché non vuoi imparare le differenze tra due leggendo un ottimo articolo su C ++ su Wikipedia ..... Questo articolo ti aiuterà moltissimo: - C ++ (Wikipedia)

Anche Google su questo argomento ti aiuterà. Chiedere a persone a caso di spiegare questo potrebbe essere complicato. IMHO, si capisce meglio leggendo piuttosto che chiedere a qualcuno

    
risposta data 16.11.2011 - 06:59
fonte

Leggi altre domande sui tag