Perché l'affermazione che le persone C# non ottengono la programmazione orientata agli oggetti?(rispetto all'orientamento alla classe)

StackOverflow https://stackoverflow.com/questions/52092

  •  09-06-2019
  •  | 
  •  

Domanda

Questo ha attirato la mia attenzione ieri sera.

All'ultimo Podcast ALT.NET Scott Bellware spiega come, al contrario di Ruby, linguaggi come C#, Java et al.non sono veramente orientati agli oggetti, piuttosto optano per la frase "orientato alla classe".Parlano di questa distinzione in termini molto vaghi senza entrare nei dettagli o discutere molto dei pro e dei contro.

Qual è la vera differenza qui e quanto conta?Quali sono poi gli altri linguaggi "orientati agli oggetti"?Sembrava piuttosto interessante, ma non voglio dover imparare Ruby solo per sapere se mi manca qualcosa.

Aggiornamento:Dopo aver letto alcune delle risposte di seguito sembra che le persone siano generalmente d'accordo sul fatto che il riferimento sia alla dattilografia.Ciò che non sono sicuro di capire ancora, però, è l'affermazione che questo alla fine cambia molto.Soprattutto se stai già eseguendo un tdd corretto con accoppiamento allentato bla bla bla.Qualcuno può mostrarmi un esempio di una cosa meravigliosa che potrei fare con Ruby che non posso fare con C# e che esemplifica questo diverso approccio oop?

È stato utile?

Soluzione

I commenti sulla digitazione delle papere qui sono più attribuiti al fatto che Ruby e Python sono di più dinamico rispetto a C#.Non ha davvero nulla a che fare con la sua natura OO.

Ciò che (credo) Bellware intendeva con questo è che in Ruby tutto è un oggetto.Anche una lezione.Una definizione di classe è un'istanza di un oggetto.Pertanto, puoi aggiungere/modificare/rimuovere il comportamento in fase di esecuzione.

Un altro buon esempio è che anche NULL è un oggetto.In rubino, tutto è LETTERALMENTE un oggetto.Avere un OO così profondo nel suo intero essere consente alcune divertenti tecniche di meta-programmazione come Method_missing.

Altri suggerimenti

In un linguaggio orientato agli oggetti, gli oggetti vengono definiti definendo oggetti piuttosto che classi, sebbene le classi possano fornire alcuni modelli utili per definizioni specifiche, ritagliate con lo stampino, di una data astrazione.In un linguaggio orientato alle classi, come ad esempio C#, gli oggetti devono essere definiti dalle classi e questi modelli sono generalmente preconfezionati, impacchettati e resi immutabili prima del runtime.Questo vincolo arbitrario secondo cui gli oggetti devono essere definiti prima del runtime e che le definizioni degli oggetti sono immutabili non è un concetto orientato agli oggetti;è orientato alla classe.

IMO, definisce davvero eccessivamente "orientato agli oggetti", ma ciò a cui si riferiscono è che Ruby, a differenza di C#, C++, Java e altri, non fa uso di definendo una classe: in realtà lavori sempre e solo direttamente con gli oggetti.Al contrario, in C#, ad esempio, definisci classi che allora devi istanziare nell'oggetto tramite la nuova parola chiave.Il punto chiave è che devi dichiarare una classe in C# o descriverla.Inoltre, in Ruby, qualunque cosa -- anche i numeri, per esempio -- è un oggetto.Al contrario, C# mantiene ancora il concetto di tipo oggetto e tipo valore.Questo in effetti, penso che illustri il punto che fanno su C# e altri linguaggi simili: object tipo e valore tipo implicare a tipo system, il che significa che hai un intero sistema di descrivendo tipi invece di lavorare solo con gli oggetti.

Concettualmente penso che OO progetto è ciò che oggigiorno fornisce l'astrazione da utilizzare per gestire la complessità dei sistemi software.Il linguaggio è uno strumento utilizzato per implementare un progetto OO: alcuni lo rendono più naturale di altri.Direi ancora che da una definizione più comune e più ampia, C# e gli altri lo sono ancora orientato agli oggetti le lingue.

Ci sono tre pilastri dell’OOP

  1. Incapsulamento
  2. Eredità
  3. Polimorfismo

Se una lingua può fare queste tre cose è una lingua OOP.

Sono abbastanza sicuro che l'argomento della lingua X faccia l'OOP meglio della lingua A che andrà avanti per sempre.

OO è talvolta definito come orientato al messaggio.L'idea è che una chiamata a un metodo (o un accesso a una proprietà) sia in realtà un messaggio inviato a un altro oggetto.Il modo in cui l'oggetto ricevente gestisce il messaggio è completamente incapsulato.Spesso il messaggio corrisponde ad un metodo che viene poi eseguito, ma questo è solo un dettaglio implementativo.Puoi ad esempio creare un gestore catch-all che viene eseguito indipendentemente dal nome del metodo nel messaggio.

L'OO statico come in C# non ha questo tipo di incapsulamento.Un massaggio ha per corrispondere a un metodo o una proprietà esistente, altrimenti il ​​compilatore si lamenterà.I linguaggi dinamici come Smalltalk, Ruby o Python supportano tuttavia OO "basato su messaggi".

Quindi in questo senso C# e altri linguaggi OO tipizzati staticamente non sono veri OO, poiché mancano di un "vero" incapsulamento.

Aggiornamento:È la nuova ondata..il che suggerisce che tutto quello che abbiamo fatto fino ad ora è superato...Sembra che stia reggendo parecchio nei podcast e nei libri..Forse questo è quello che hai sentito.

Finora ci siamo occupati di classi statiche e non scatenato il potere dello sviluppo orientato agli oggetti.Abbiamo fatto "Dev basato su classe". Le classi sono modelli fissi/statici per creare oggetti.Tutti gli oggetti di una classe sono creati uguali.

per esempio.Giusto per illustrare ciò di cui stavo blaterando...lasciami prendere in prestito uno snippet di codice Ruby dallo screencast di PragProg che ho appena avuto il privilegio di guardare.Lo "sviluppo basato su prototipi" sfuma il confine tra oggetti e classi.non c'è differenza.

animal = Object.new                  # create a new instance of base Object

def animal.number_of_feet=(feet)     # adding new methods to an Object instance. What?
  @number_of_feet = feet
end
def animal.number_of_feet
  @number_of_feet
end

cat = animal.clone          #inherits 'number_of_feet' behavior from animal
cat.number_of_feet = 4

felix = cat.clone           #inherits state of '4' and behavior from cat
puts felix.number_of_feet   # outputs 4

L'idea è che sia un modo più potente per ereditare lo stato e il comportamento rispetto alla tradizionale ereditarietà basata sulle classi.Ti dà maggiore flessibilità e controllo in alcuni scenari "speciali" (che devo ancora capire).Ciò consente cose come Mix-in (riutilizzo del comportamento senza ereditarietà della classe).

Sfidando i concetti primitivi di base del modo in cui pensiamo ai problemi, la "vera OOP" è come "Matrix" in un certo senso...Continui ad andare in loop, WTF.Come questo..dove la classe base di Container può essere un Array o un Hash in base a quale lato di 0,5 è il numero casuale generato.

class Container < (rand < 0.5 ? Array : Hash)
end

Ruby, Javascript e la nuova brigata sembrano essere i pionieri di questo.Sono ancora fuori su questo...leggendo e cercando di dare un senso a questo nuovo fenomeno.Sembra essere potente..troppo potente..Utile?Ho bisogno che i miei occhi siano aperti un po' di più.Tempi interessanti..questi.

Ho ascoltato solo i primi 6-7 minuti del podcast che ha suscitato la tua domanda.Se il loro intento è quello di dire che C# non è un linguaggio puramente orientato agli oggetti, in realtà è corretto.Tutto in C# non è un oggetto (almeno le primitive non lo sono, sebbene il boxing crei un oggetto contenente lo stesso valore).In Ruby tutto è un oggetto.Daren e Ben sembrano aver coperto tutti gli argomenti nella loro discussione sulla "digitazione a papera", quindi non lo ripeterò.

Se questa differenza (tutto un oggetto rispetto a tutto ciò che non è un oggetto) sia materiale/significativa è una domanda a cui non posso rispondere prontamente perché non ho una profondità sufficiente in Ruby per confrontarla con C#.Quelli di voi che conoscono Smalltalk (io no, anche se vorrei saperlo) probabilmente hanno guardato il movimento Ruby con un certo divertimento da quando è stato il primo linguaggio OO puro 30 anni fa.

Forse alludono alla differenza tra la digitazione a papera e le gerarchie di classe?

se cammina come un'anatra e starnazza come un'anatra, fai finta che sia un'anatra e prendila a calci.

In C#, Java ecc.il compilatore si preoccupa molto di:Sei autorizzato a fare questa operazione su quell'oggetto?

Orientamento agli oggetti vs.Class Oriented potrebbe quindi significare:Il linguaggio si preoccupa degli oggetti o delle classi?

Ad esempio:In Python, per implementare un oggetto iterabile, devi solo fornire un metodo __iter__() che restituisce un oggetto a cui è assegnato un metodo denominato next().Questo è tutto:Nessuna implementazione dell'interfaccia (non esiste una cosa del genere).Nessuna sottoclasse.Sto solo parlando come un'anatra/iteratore.

MODIFICARE: Questo post è stato votato mentre riscrivevo tutto.Mi dispiace, non lo farò mai più.Il contenuto originale includeva consigli per imparare quante più lingue possibile e di non preoccuparsi di ciò che i medici linguistici pensano/dicono di una lingua.

Quello era davvero un podcast astratto!
Ma capisco a cosa mirano: sono semplicemente abbagliati da Ruby Sparkle.Ruby ti permette di fare cose a cui i programmatori basati su C e Java non penserebbero nemmeno + combinazioni di queste cose ti permettono di raggiungere possibilità inimmaginabili.Aggiungere nuovi metodi a una classe String incorporata perché ne hai voglia, passare blocchi di codice senza nome affinché altri possano eseguirli, mixin ...Le persone convenzionali non sono abituate a oggetti che cambiano troppo lontano dal modello di classe.Sicuramente c'è un mondo completamente nuovo là fuori..

Per quanto riguarda i ragazzi del C# che non sono abbastanza OO...non prendertela a cuore..Prendilo come quello che dici quando sei sbalordito dalle parole.Ruby fa questo alla maggior parte delle persone.
Se dovessi consigliare una lingua da imparare in questo decennio...sarebbe Ruby.Sono felice di averlo fatto..Sebbene alcune persone possano rivendicare Python.Ma è come la mia opinione..Uomo!:D

Non penso che si tratti specificamente della battitura a papera.Ad esempio, C# supporta già la digitazione duck limitata: un esempio potrebbe essere che puoi utilizzare foreach on Qualunque classe che implementa MoveNext e Current.

Il concetto di duck-typing è compatibile con linguaggi tipizzati staticamente come Java e C#, è fondamentalmente un'estensione della riflessione.

Questo è davvero il caso della tipizzazione statica e dinamica.Entrambi sono veri e propri OO, nella misura in cui esiste una cosa del genere.Al di fuori del mondo accademico non vale davvero la pena discuterne.

In entrambi i casi è possibile scrivere codice spazzatura.In entrambi i casi è possibile scrivere un ottimo codice.Non c'è assolutamente nulla di funzionale che un modello possa fare che l'altro non possa fare.

La vera differenza sta nella natura della codifica eseguita.I tipi statici riducono la libertà, ma il vantaggio è che tutti sanno con cosa hanno a che fare.L'opportunità di modificare le istanze al volo è molto potente, ma il prezzo è che diventa difficile sapere con cosa hai a che fare.

Ad esempio per Java o C# intellisense è semplice: l'IDE può rapidamente produrre un elenco a discesa di possibilità.Per Javascript o Ruby questo diventa molto più difficile.

Per alcune cose, ad esempio produrre un'API con cui qualcun altro codificherà, c'è un reale vantaggio nella digitazione statica.Per altri, ad esempio producendo rapidamente prototipi, il vantaggio va alla dinamica.

Vale la pena comprendere entrambi nella cassetta degli attrezzi delle tue competenze, ma non è affatto importante quanto comprendere quello che già usi in modo approfondito.

Object Oriented è un concetto.Questo concetto si basa su alcune idee.I nomi tecnici di queste idee (in realtà piuttosto principi che si sono evoluti nel tempo e non ci sono dalla prima ora) sono già stati dati sopra, non li ripeterò.Sto piuttosto spiegandolo nel modo più semplice e non tecnico possibile.

L'idea della programmazione OO è che ci siano oggetti.Gli oggetti sono piccole entità indipendenti.Queste entità potrebbero avere informazioni incorporate oppure no.Se dispongono di tali informazioni, solo l'entità stessa può accedervi o modificarle.Le entità comunicano tra loro inviandosi messaggi tra loro.Confrontatelo con gli esseri umani.Gli esseri umani sono entità indipendenti, hanno dati interni memorizzati nel cervello e interagiscono tra loro comunicando (ad es.parlando tra loro).Se hai bisogno della conoscenza del cervello di qualcun altro, non puoi accedervi direttamente, devi fargli una domanda e lui potrebbe risponderti, dicendoti quello che volevi sapere.

E questo è fondamentalmente tutto.Questa è la vera idea alla base della programmazione OO.Scrivendo queste entità, definisci la comunicazione tra loro e falle interagire insieme per formare un'applicazione.Questo concetto non è legato ad alcuna lingua.È solo un concetto e se scrivi il codice in C#, Java o Ruby, non è importante.Con un po' di lavoro extra questo concetto può essere realizzato anche in C puro, anche se è un linguaggio funzionale ma offre tutto ciò di cui hai bisogno per il concetto.

Diversi linguaggi hanno ormai adottato questo concetto di programmazione OO e ovviamente i concetti non sono sempre uguali.Alcune lingue consentono ciò che altre lingue vietano, ad esempio.Ora uno dei concetti coinvolti è il concetto di classi.Alcune lingue hanno lezioni, altre no.Una classe è un progetto di come appare un oggetto.Definisce l'archiviazione interna dei dati di un oggetto, definisce i messaggi che un oggetto può comprendere e se esiste ereditarietà (che è non obbligatorio per la programmazione OO!), le classi definiscono anche da quale altra classe (o classi se è consentita l'ereditarietà multipla) questa classe eredita (e quali proprietà se esiste l'ereditarietà selettiva).Una volta creato un progetto di questo tipo, ora puoi generare una quantità illimitata di oggetti costruiti secondo questo progetto.

Tuttavia, ci sono linguaggi OO che non hanno classi.Come vengono quindi costruiti gli oggetti?Bene, di solito in modo dinamico.Per esempio.è possibile creare un nuovo oggetto vuoto e quindi aggiungere dinamicamente una struttura interna come variabili di istanza o metodi (messaggi).Oppure puoi duplicare un oggetto già esistente, con tutte le sue proprietà e poi modificarlo.O eventualmente unire due oggetti in uno nuovo.A differenza dei linguaggi basati su classi, questi linguaggi sono molto dinamici, poiché puoi generare oggetti dinamicamente durante il runtime in modi a cui nemmeno lo sviluppatore ha pensato quando ha iniziato a scrivere il codice.

Solitamente questa dinamica ha un prezzo:Più una lingua è dinamica, più oggetti di memoria (RAM) verranno sprecati e più tutto diventerà lento poiché anche il flusso del programma è estremamente dinamico ed è difficile per un compilatore generare codice efficace se non ha la possibilità di prevedere il codice o il flusso di dati.I compilatori JIT possono ottimizzarne alcune parti durante il runtime, una volta che conoscono il flusso del programma, tuttavia poiché questi linguaggi sono così dinamici, il flusso del programma può cambiare in qualsiasi momento, costringendo il JIT a eliminare tutti i risultati della compilazione e ricompilare lo stesso codice ancora e ancora.

Ma questo è un piccolo dettaglio di implementazione: non ha nulla a che fare con il principio OO di base.Non è detto da nessuna parte che gli oggetti debbano essere dinamici o debbano essere modificabili durante il runtime.Wikipedia lo dice molto bene:

Le tecniche di programmazione possono includere caratteristiche come nascondiglio delle informazioni, astrazione dei dati, incapsulamento, modularità, polimorfismo e ereditarietà.

http://en.wikipedia.org/wiki/Object-oriented_programming

Essi Maggio o loro potrebbe non esserlo.Tutto questo non è obbligatorio.Obbligatoria è solo la presenza degli oggetti e che questi debbano avere modo di interagire tra loro (altrimenti gli oggetti sarebbero piuttosto inutili se non potessero interagire tra loro).

Hai chiesto:"Qualcuno può mostrarmi un esempio di una cosa meravigliosa che potrei fare con Ruby che non posso fare con C# e che esemplifica questo diverso approccio oop?"

Un buon esempio è il record attivo, l'ORM integrato nei binari.Le classi del modello vengono create dinamicamente in fase di esecuzione, in base allo schema del database.

Probabilmente si tratta davvero di ciò che queste persone vedono fare dagli altri in C# e Java rispetto a C# e Java che supportano OOP.La maggior parte dei linguaggi può essere utilizzata in diversi paradigmi di programmazione.Ad esempio, puoi scrivere codice procedurale in C# e schema e puoi eseguire una programmazione in stile funzionale in Java.Si tratta più di ciò che stai cercando di fare e di ciò che la lingua supporta.

Ci proverò.

Python e Ruby sono di tipo duck.Per generare qualsiasi codice gestibile in questi linguaggi, è praticamente necessario utilizzare lo sviluppo basato su test.Pertanto, è molto importante per uno sviluppatore inserire facilmente le dipendenze nel proprio codice senza dover creare un gigantesco framework di supporto.

Il successo dell'inserimento delle dipendenze dipende dalla disponibilità di un modello a oggetti abbastanza buono.I due sono una sorta di due facce della stessa medaglia.Se capisci davvero come utilizzare l'OOP, dovresti creare per impostazione predefinita progetti in cui le dipendenze possano essere facilmente inserite.

Poiché l'inserimento delle dipendenze è più semplice nei linguaggi tipizzati dinamicamente, gli sviluppatori Ruby/Python ritengono che il loro linguaggio comprenda le lezioni di OO molto meglio di altre controparti tipizzate staticamente.

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