Domanda

Nota : questa domanda è un estratto modificato da un blog di distacco ho scritto qualche mese fa. Dopo aver posizionato un link al blog in un commento su Programmers.SE qualcuno chiesto che ho posto una domanda qui in modo che si potrebbe rispondere. Questo intervento è il mio più popolari, come la gente sembra tipo "Non capisco la programmazione orientata agli oggetti" in Google molto . Sentitevi liberi di rispondere qui, o in un commento in Wordpress.

Quello che è programmazione orientata agli oggetti? Nessuno mi ha dato una soddisfacente risposta. Mi sento come non sarà possibile ottenere una definizione buona da qualcuno che va in giro a dire “oggetto” e “Object-oriented” con il suo naso in aria. Né si otterrà un buon Definizione da qualcuno che ha fatto nient'altro orientata agli oggetti programmazione. Nessuno che capisce procedurale e orientata agli oggetti programmazione ha mai dato a me un idea coerente di ciò che un programma orientato agli oggetti in realtà fa.

Qualcuno può per favore mi dia loro idee dei vantaggi della programmazione orientata agli oggetti?

È stato utile?

Soluzione

Pensate a software come macchina o linea di assemblaggio che esiste all'interno del computer. Alcune materie prime e componenti vengono alimentati nella macchina, e segue un insieme di procedure per trasformarli in qualche prodotto finale. Le procedure sono impostati per eseguire un'operazione specifica su alcune materie prime o componente a un insieme specifico di parametri (ad esempio tempo, temperatura, distanza, ecc) in un ordine particolare. Se i dettagli dell'operazione da eseguire erano errate, o sensori della macchina non sono calibrati correttamente, o se alcune materie prime o componente non era entro livelli qualitativi previsti, potrebbe cambiare esito dell'operazione e il prodotto non risulterebbe come previsto.

Tale macchina è molto rigida nel suo funzionamento e ingressi accettabili. Macchine non mettono in discussione l'intelligenza dei progettisti, né il suo ambiente operativo corrente. Essa continuerà a seguire le procedure il più a lungo è indirizzato a. Anche se un cambiamento di materie prime o componenti potrebbe avere un effetto drammatico su quanto accaduto nelle operazioni successive, la macchina si comporta ancora le sue procedure. Il processo dovrebbe essere rivisto per vedere quali cambiamenti alle procedure erano necessarie per compensare e produrre il risultato desiderato. Una modifica di progettazione o configurazione del prodotto potrebbe anche richiedere un cambiamento significativo alle operazioni eseguite o il loro ordine. Sebbene i responsabili della produzione rapidamente imparato l'importanza delle operazioni isolare il più possibile per ridurre gli effetti indesiderati tra loro, un sacco di ipotesi sono realizzati i componenti condizione sono in quanto sottoposti a lavorazione; ipotesi che potrebbe non essere rilevato fino a che il prodotto finale è nelle mani dell'utente in qualche ambiente operativo diverso.

Questo è ciò che la programmazione procedurale è come.

Quale oggetto-orientamento fornisce un modo per rimuovere le assunzioni della condizione dei componenti; quindi, le operazioni da eseguire su tale componente e come integrare nel prodotto finale. In altre parole, OOP è come prendere i dettagli del processo per trattare con qualche componente particolare e darlo a una macchina più piccola da fare. La macchina più grande responsabile del processo racconta la macchina specifica componente quale operazione si aspetta di essere fatto, ma lascia i dettagli per i gradini della macchina specifica componente da gestire.

Come ai vantaggi dell'oggetto orientamento rispetto al software non orientato agli oggetti:

  • comportamento dei componenti specifici - rendendo dettagli su come gestire un componente particolare la responsabilità della macchina specifico componente minore assicura ogni volta che componente viene gestita, relativa macchina farà adeguatamente;
  • polimorfico espressioni - perché le operazioni di macchine su componenti definiscono le prestazioni su misura per la sua particolare componente, lo stesso messaggio inviato a macchine diverse può agire in modo diverso;
  • tipo astrazione - spesso ha senso per diversi tipi di componenti da utilizzare lo stesso vocabolario delle operazioni loro macchine fanno;
  • separazione degli interessi - lasciando dettagli su componenti specifici alle loro macchine mezzi macchina processo deve solo gestire le più generali, grandi preoccupazioni del suo processo ei dati necessari per gestirlo; In più, è meno probabilità di essere colpiti dai cambiamenti di altri componenti;
  • adattabilità - componenti che si concentrano sulla loro area di specializzazione può essere adattato all'uso imprevisto semplicemente cambiando i componenti che utilizza, o rendendola disponibile ad un'altra macchina processo;
  • il riutilizzo del codice -. Componenti con un focus stretto e una maggiore adattabilità possono sfruttare il loro costo di sviluppo per essere oggetto di un uso più spesso

Altri suggerimenti

Dal tuo blog, sembra che si ha familiarità con sia imperativo e programmazione funzionale, e che si ha familiarità con i concetti di base coinvolti nella programmazione orientata agli oggetti, ma hai appena mai veramente avuto un "click" da ciò che lo rende utile. Cercherò di spiegare in termini di quella conoscenza, e la speranza che sia utile a voi.

Al suo interno, OOP è un modo per utilizzare il paradigma imperativo di gestire meglio elevati gradi di complessità creando strutture dati "intelligenti" modello dominio del problema. In un programma (di serie procedurale non orientata agli oggetti), hai due cose fondamentali: variabili, e il codice che sa cosa fare con loro. Il codice prende input dall'utente e varie altre fonti, lo memorizza in variabili, opera su di esso, e produce dati di uscita che va all'utente o varie altre posizioni.

programmazione orientata agli oggetti è un modo per semplificare il programma assumendo che modello di base e ripetendo su scala minore. Proprio come un programma è una grande raccolta di dati con codice che sa cosa fare con esso, ogni oggetto è un piccolo pezzo di dati associato al codice che sa cosa fare con esso.

Per abbattere il dominio del problema in pezzi più piccoli e fare in modo quanti più dati possibile è associato direttamente a codice che sa cosa fare con esso, si rendono molto più facile ragionare sul processo nel suo insieme e anche di i sub-temi che compongono il processo.

Per il raggruppamento dei dati in classi di oggetti, è possibile centralizzare codice relativo a tali dati, rendendo relativo codice più facile da trovare entrambi e per eseguire il debug. E incapsulando i dati dietro specificatori di accesso e solo accedervi attraverso metodi, (o in, se il vostro supporto per il linguaggio di loro,) si riducono notevolmente il rischio di danneggiamento dei dati o la violazione delle invarianti.

E utilizzando ereditarietà e polimorfismo, è possibile riutilizzare preesistente classi, personalizzandoli in base alle proprie specifiche esigenze, senza dover né modificare le originali o riscrivere tutto da zero. (Che è una cosa non si dovrebbe mai fare , se si può evitare.) Basta stare attenti a capire il vostro oggetto di base, o si potrebbe finire con assassino canguri .

Per me, questi sono i principi fondamentali della programmazione orientata agli oggetti: la complessità di gestione, il codice di centralizzazione e una migliore modellazione di problem-dominio attraverso la creazione di classi di oggetti, ereditarietà e polimorfismo, e una maggiore sicurezza senza sacrificare la potenza o il controllo attraverso l'uso di incapsulamento e proprietà. Spero che questo ti aiuta a capire il motivo per cui molti programmatori lo trovano utile.

EDIT: In risposta alla domanda di Joel nei commenti,

Può spiegare che cosa un "programma orientato agli oggetti" contiene (Diverso da questi defintions fantasia che hai descritto) che è fondamentalmente diverso da un programma imperativo? Come si fa a "ottiene il rotolamento palla?"

Un po 'di responsabilità qui. Il mio modello di "un programma orientato agli oggetti" è fondamentalmente il modello di Delphi, che è molto simile al C # /. NET modello da quando sono stati creati da ex membri del team Delphi. Quello che sto dicendo qui potrebbe non essere applicabile, o non si applica tanto, in altri linguaggi OO.

Un programma orientato agli oggetti è uno in cui tutta la logica è strutturato attorno agli oggetti. Naturalmente questo deve essere bootstrap da qualche parte. Il vostro programma tipico Delphi contiene l'inizializzazione codice che crea un oggetto Singleton chiamato Application. All'inizio del programma, che chiama Application.Initialize, quindi una chiamata a Application.CreateForm per ogni forma che si desidera caricare in memoria fin dal principio, e quindi Application.Run, che visualizza il modulo principale sullo schermo e si avvia il ciclo di input / evento che costituisce la nucleo di qualsiasi pr informatico interattivoograms.

Applicazione e i moduli sondaggio per gli eventi in arrivo dal sistema operativo e tradurli in chiamate di metodo sul vostro oggetto. Una cosa che è molto comune è l'uso di gestori di eventi, o "delegati" NET-parlare. Un oggetto ha un metodo che dice: "fare X e Y, ma anche controllare per vedere se questo particolare gestore di eventi viene assegnato, e lo chiamano se lo è." Un gestore di eventi è un puntatore metodo - molto semplice chiusura che contiene un riferimento al metodo ed un riferimento all'istanza dell'oggetto - che viene utilizzato per estendere il comportamento degli oggetti. Per esempio, se ho un oggetto pulsante sulla mia forma, ho personalizzarne il comportamento allegando un gestore di eventi OnClick, che provoca qualche altro oggetto per eseguire un metodo quando il pulsante viene premuto.

Quindi, in un programma orientato agli oggetti, la maggior parte del lavoro viene fatto attraverso la definizione di oggetti con determinate responsabilità e li collega tra loro, sia attraverso il metodo puntatori o da un oggetto chiamando direttamente un metodo definito nella interfaccia pubblica di un altro oggetto. (E ora siamo di nuovo a incapsulamento.) Questa è un'idea che non avevo alcun concetto di tornare prima ho preso OOP classi in un college.

Credo che OOP è fondamentalmente solo un nome dato a qualcosa che potrebbe essere stato tentato di fare lungo la strada, come mi è stato.

Una volta, quando ero un programmatore bambino, anche in Fortran, c'era una tale cosa come un puntatore a una subroutine. E 'davvero utile per essere in grado di passare un puntatore a una subroutine come argomento di un'altra subroutine.

Poi la prossima cosa che sarebbe davvero utile potrebbe essere quella di memorizzare un puntatore ad una subroutine all'interno di un record di una struttura di dati. In questo modo, si potrebbe dire che il record "sa" come fare operazioni su se stessa.

Non sono sicuro se mai costruito che in Fortran, ma è facile da fare in C e dei suoi discendenti.

Quindi sotto, si tratta di un semplice e un'idea utile che tu possa aver avuto la tentazione di fare da soli, ed è più facile da fare in più recenti lingue, anche se alcune persone lo ha trasformato in un carro gigante pieno di parole d'ordine spaventosi.

C'è diversi tipi di sistemi OO, ed è difficile ottenere una definizione tutti saranno d'accordo. Piuttosto che cercare di mostrare come OO di Java è simile all'oggetto Common Lisp Sistema, inizierò con qualcosa di più convenzionale, passo dopo passo.

Si supponga di avere un sacco di oggetti esistenti come dati sparsi. Punti, per esempio, potrebbero essere elementi di un X, Y, e Z una matrice. Al fine di prendere in considerazione un punto di per sé, ha senso mettere insieme tutti i dati in qualcosa di simile a un struct C.

Ora, per qualsiasi oggetto dei dati, abbiamo i dati tutti insieme. Tuttavia, in un programma di procedura, il codice è sparsa. Supponiamo abbiamo a che fare con forme geometriche. C'è una grande funzione per disegnare forme, e ha bisogno di conoscere tutte le forme. C'è una grande funzione per trovare spazio, e un altro per il perimetro. Il codice per un cerchio è sparsa attraverso molteplici funzioni, e al fine di aggiungere un altro tipo di forma abbiamo bisogno di sapere quali funzioni al cambiamento. In un sistema orientato agli oggetti, raccogliamo le funzioni nello stesso tipo di cosa (class) come dati. Pertanto, se vogliamo guardare tutto il codice cerchio, è lì nella definizione Circle, e se vogliamo aggiungere un Quartercircle semplicemente scriviamo sua classe e noi abbiamo il codice.

Un vantaggio collaterale di questo è che siamo in grado di mantenere invarianti di classe, le cose che sono vere su ogni membro della classe. Limitando codice esterno alla classe di fare scherzi direttamente con i membri di dati di classe, abbiamo tutto il codice che può cambiare i dati della classe in un unico luogo, e possiamo confermare che non fa nulla irregolare (come avere un triangolo con una gamba sola più lungo degli altri due combinate). Questo significa che possiamo contare su alcune proprietà di ogni membro della classe, e non c'è bisogno di controllare per vedere se un oggetto è sano di mente ogni volta che lo usiamo.

Il vantaggio principale è dotato di ereditarietà e polimorfismo. Con la definizione di tutte queste varie forme come sottoclassi di una classe chiamata Shape, possiamo avere il nostro codice manipolare Shapes, ed è il lavoro dei suboggetti forma per fare tutto ciò che è richiesto dal manipolazioni. Questo significa che non abbiamo bisogno toccare il vecchio codice testato quando aggiungiamo nuove forme o perfezionare il comportamento di quelli più vecchi. Abbiamo automaticamente vecchio codice che può prendere direttamente vantaggio di nuovo codice. Invece di fare il codice di controllo a conoscenza di tutte le diverse forme possibili, e dovendo mantenere le funzioni che sono a conoscenza di tutte le diverse forme possibili, ci limitiamo a che fare con le forme e le loro proprietà, mantenendo sottoclassi Shape. Questo semplifica il codice di controllo.

Abbiamo diversi vantaggi qui. Dal momento che abbiamo invarianti di classe, possiamo ragionare su grandi oggetti dati nella stessa ragione modo in cui circa tipi predefiniti, il che significa spesso siamo in grado di scindere i concetti complessi in quelli più semplici. Dal momento che il codice cerchio è in gran parte contenuta in Circle, abbiamo aumentato località. Dal momento che non ci sono concetti di un cerchio sparsi attraverso diverse funzioni diverse in luoghi diversi, otteniamo meno accoppiamento tra le routine, e non devono preoccuparsi di tenerli in sincronia. Dal momento che le classi sono, in effetti, i tipi, si può approfittare del sistema di tipo esistente per catturare l'uso incompatibile delle nostre classi.

OO ha molte definizioni diverse, sì. Sono sicuro che si può trovare un sacco di questi da soli. Personalmente, come Rees Re: OO come un modo per dar loro un senso. Sto indovinando che hai letto che già da quando lei cita Paul Graham. (Lo consiglio a chiunque sia interessato a OO.) Vado a più o meno adottare la definizione di Java qui {1,2,3,7,8,9}.

La questione dell'utilità di OO, in particolare il modo in cui mi avvicino, merita una risposta molto più grande con qualche migliaio di righe di codice (anche al fine di non essere solo un po 'di affermazioni). Tuttavia, ecco una sintesi di quella ipotetica documento.

Non credo OO è terribilmente utile a piccola scala, dico, di un qualche centinaio di righe. In particolare, linguaggi OO senza buone influenze funzionali tendono a renderlo veramente doloroso per ottenere le cose semplici fatte con qualsiasi tipo di raccolta o qualsiasi cosa che ha bisogno di molti tipi di dati. Questo è dove la maggior parte modelli di progettazione entrano in gioco; stanno cerotti sulla bassa potenza del linguaggio sottostante .

A circa un migliaio di linee, comincia a essere più difficile tenere traccia di tutte le operazioni e le strutture dati e come essi si riferiscono. Aiuta, a questo punto, di avere un modo per organizzare in modo esplicito le strutture e le operazioni sui dati, per disegnare i confini del modulo e definire le responsabilità, e di avere un modo conveniente per capire quelle definizioni, mentre si sta cercando di programma contro di loro.

Java-ish OO è una soluzione a metà strada a questi problemi che succede ad aver vinto il concorso di popolarità. Perché è lo stesso meccanismo che la gente Java si applicano ai problemi di piccole dimensioni creati da un linguaggio sottodimensionato, si tende a iniziare a guardare più come una soluzione magica a tutto ciò che solo un modo per essere sempre organizzati. Persone che hanno familiarità con la programmazione funzionale tendono a preferire altre soluzioni, come CLOS o classi di tipo di Haskell, o un modello metaprogrammazione quando bloccato in C ++, oppure (come me, lavora quotidianamente in C #) l'uso OO, ma proprio non capisco tutto quello che entusiasta .

tentativi OOP di modellare i concetti del mondo reale in termini di oggetti e le interazioni tra di loro. Come esseri umani, tendiamo a elaborare il mondo in termini di oggetti. Il mondo è pieno di oggetti che hanno determinate proprietà e in grado di fare cose come interagire con altri oggetti. OOP permette di modellare il mondo in termini simili. Ad esempio,

  • Persona è un oggetto. Una persona ha alcune proprietà, come l'età e il sesso. Una persona può fare le cose:. Mangiare, dormire, guidare una macchina
  • Car è anche un oggetto (anche se di tipo diverso). Ha anche proprietà come marca, modello e anno. Una macchina può fare cose:. Mossa

Ma una macchina non può muoversi da sola, ha bisogno di una persona di guidare -. Interazione tra gli oggetti

strutture

OOP = dati + message passing + eredità, che sono tutti evoluzioni logiche a modelli di programmazione.

OOP può essere compreso (dai programmatori) in circa 90 secondi (vedere il mio profilo per un link). I concetti sono molto semplici.

Come applicare è un altro discorso. Solo perché si sa come swing un martello non significa che si sa come progettare e costruire una casa. ; -)

ho scritto un post sul blog qualche tempo fa che potreste trovare utili: procedurale vs . OOP spiegato .

Il modo in cui ho capito che è:

Prima della programmazione orientata agli oggetti, si doveva programmazione strutturata . Tutto è centrata intorno al processo. La prima domanda è arrivata a porsi è " Quello che voglio fare con le informazioni? ".

Con la programmazione orientata agli oggetti, è centrata attorno i dati. La prima domanda è arrivata a porsi è " informazioni Strega ho bisogno di offerte con? ". Questo rende più facile l'astrazione.

Dal momento che si capisce le strutture, e si capisce puntatori a funzione, e si capisce struct con puntatori a funzione, dal tuo punto di vista che definirei programmazione orientata agli oggetti semplicemente come "la programmazione, con uso pesante di struct che hanno puntatori a funzione". E 'ancora la programmazione nel senso tradizionale - è che tutti i dati, e il codice che agisce sui dati. La differenza è semplicemente come tutte quelle informazioni è definito e come ci si avvicina definirlo.

Forse una semplificazione sopra è che la programmazione tradizionale è "codice, con alcune strutture di dati", e programmazione orientata agli oggetti è "strutture di dati, con un codice". Entrambi hanno ancora strutture di dati, ed entrambi hanno ancora il codice. Programmazione orientata agli oggetti, quindi, non è altro che l'atto di definizione dei tipi di dati su fronte, e far rispettare i contratti di come comunicano tramite set di funzioni.

Come avete osservato, v'è una grande classe di applicazioni per le quali questo non è un ottimo modo per implementare una soluzione. Ti sembra di vivere in un mondo prevalentemente costituito da tali applicazioni. Nel tuo post sul blog che si menzione guardando implementazioni del "99 bottiglie di birra" problema (il vostro "vetrina di programmazione preferito"). 99 bottiglie di birra è certamente parte di quella categoria. Cercando di capire programmazione orientata agli oggetti, cercando in implementazioni di 99 bottiglie di birra è un po 'come cercare di capire alto architettura aumento cercando in una casa sull'albero. Anche una casa sull'albero molto ben costruito può soltanto insegnare tanto.

TL; DR: programmazione OO è come programmazione tradizionale, tranne che si concentrerà più del vostro sforzo nella definizione delle strutture dati in anticipo, e si dispone di quelle strutture di dati comunicano tra loro tramite puntatori a funzione.

Credo che la pagina di Wikipedia è un buon posto per ottenere i fondamentali:
http://en.wikipedia.org/wiki/Object-oriented_programming

In sostanza l'idea è che la programmazione procedurale, che è ciò che OOP stava cercando di migliorare, si è concentrato sui processi in corso di modellazione. OOP si sposta verso un modello in cui l'attenzione si concentra sulle "cose" si sta modellando, ed i processi ei dati di quelle cose sono contenuti all'interno di quelle cose.

Così, ad esempio, diciamo che si stavano progettando un'applicazione per tenere traccia di un elenco di attività. In programmazione procedurale, le entità di livello superiore nel modello sarebbero i processi che si verificano, come ad esempio la creazione di un'attività, la rimozione di un compito, modificando le informazioni compito, ecc In un modello OOP, si dovrebbe invece concentrarsi sulla creazione di un task, e pensare a quali dati e processi che compito dovrebbe essere responsabile. E poi concentrarsi su ciò che altri oggetti compito dovrebbe interagire con, ad esempio, eventualmente, una nota o qualcosa se si desidera mantenere le note circa le attività.

Mi auguro che aiuta. Basta continuare a leggere su di esso e guardare il codice e sarà improvvisamente "click". Quella era la mia esperienza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
scroll top