La programmazione funzionale è un superset di object oriented?

26

La programmazione più funzionale che faccio, più mi sembra che aggiunga un ulteriore livello di astrazione che sembra il modo in cui uno strato di cipolla è - che comprende tutti i livelli precedenti.

Non so se questo è vero, quindi, andando fuori dai principi OOP con cui ho lavorato per anni, qualcuno può spiegare in che modo funzionale o non ne descrive accuratamente uno qualsiasi: Incapsulamento, Astrazione, Eredità, Polimorfismo

Penso che tutti possiamo dire, sì, ha incapsulamento tramite tuple, o le tuple contano tecnicamente come fatto di "programmazione funzionale" o sono solo un'utilità della lingua?

So che Haskell può soddisfare il requisito delle "interfacce", ma ancora una volta non è certo che il metodo sia un fatto funzionale? Immagino che il fatto che i funtori abbiano una base matematica, potresti dire che sono un aspettativa definita di funzionamento, forse?

Per favore, spiega in dettaglio come ritieni che il funzionale soddisfi o no i 4 principi dell'OOP.

Modifica: Capisco bene le differenze tra paradigma funzionale e paradigma orientato agli oggetti e mi rendo conto che ci sono un sacco di lingue multiparadigm in questi giorni che possono fare entrambe le cose. In realtà sto solo cercando le definizioni di come un vero fp (pensa il purista, come haskell) può fare una delle 4 cose elencate, o perché non può farne nessuna. vale a dire "L'incapsulamento può essere fatto con chiusure" (o se ho torto in questa convinzione, si prega di indicare perché).

    
posta Jimmy Hoffa 03.09.2012 - 07:47
fonte

6 risposte

43

La programmazione funzionale non è uno strato sopra OOP; è un paradigma completamente diverso. È possibile fare OOP in uno stile funzionale (F # è stato scritto proprio per questo scopo) e dall'altra parte dello spettro hai cose come Haskell, che rifiuta esplicitamente i principi dell'oggetto orientamento.

Puoi eseguire incapsulamento e astrazione in qualsiasi linguaggio sufficientemente avanzato da supportare moduli e funzioni. OO fornisce meccanismi speciali per l'incapsulamento, ma non è qualcosa di inerente a OO. Il punto di OO è la seconda coppia che hai menzionato: ereditarietà e polimorfismo. Il concetto è formalmente noto come sostituzione di Liskov e non è possibile ottenerlo senza il supporto a livello di linguaggio per la programmazione orientata agli oggetti. (Sì, è possibile falsificarlo in alcuni casi, ma perdi molti dei vantaggi che OO offre al tavolo.)

La programmazione funzionale non si concentra sulla sostituzione di Liskov. Si concentra sull'aumentare il livello di astrazione e sulla minimizzazione dell'uso di stati e routine mutabili con "effetti collaterali", che è un termine di programmatori funzionali come usare per fare routine che effettivamente fanno qualcosa (invece di calcolare semplicemente qualcosa) suono spaventoso. Ma ancora, sono paradigmi completamente separati, che possono essere usati insieme o meno, a seconda della lingua e dell'abilità del programmatore.

    
risposta data 03.09.2012 - 08:07
fonte
10

Trovo la seguente intuizione utile per confrontare OOP e FP.

Invece di considerare FP come un superset di OOP, pensa a OOP e FP come a due modi alternativi di guardare un simile modello di calcolo sottostante in cui hai:

  1. Alcune operazioni eseguite,
  2. alcuni argomenti di input per l'operazione,
  3. alcuni dati / parametri fissi che possono influenzare la definizione dell'operazione,
  4. qualche valore risultato e
  5. probabilmente un effetto collaterale.

In OOP questo è catturato da

  1. Un metodo che viene eseguito,
  2. gli argomenti di input di un metodo,
  3. l'oggetto su cui è invocato il metodo, contenente alcuni dati locali sotto forma di variabili membro
  4. il valore di ritorno del metodo (eventualmente vuoto),
  5. gli effetti collaterali del metodo.

In FP questo viene catturato da

  1. Una chiusura che viene eseguita,
  2. gli argomenti di input della chiusura,
  3. le variabili catturate della chiusura,
  4. il valore di ritorno della chiusura,
  5. i possibili effetti collaterali della chiusura (in puro linguaggio come Haskell, questo avviene in modo molto controllato).

Con questa interpretazione, un oggetto può essere visto come una collezione di chiusure (i suoi metodi) che catturano tutte le stesse variabili non locali (le variabili membro comuni dell'oggetto a tutte le chiusure nella collezione). Questa vista è anche supportata dal fatto che nelle chiusure linguistiche orientate agli oggetti vengono spesso modellate come oggetti con esattamente un metodo.

Penso che i diversi punti di vista provengano dal fatto che la vista orientata agli oggetti è centrata sugli oggetti (i dati) mentre la vista funzionale è centrata sulle funzioni / chiusure (le operazioni).

    
risposta data 03.09.2012 - 10:03
fonte
8

Dipende da chi chiedi una definizione di OOP. Chiedi a cinque persone e probabilmente otterrai sei definizioni. Wikipedia dice :

Attempts to find a consensus definition or theory behind objects have not proven very successful

Quindi ogni volta che qualcuno dà una risposta molto definitiva, prendila con un pizzico di sale.

Detto questo, c'è una buona argomentazione da fare che, sì, FP è un superset di OOP come paradigma. In particolare la definizione di Alan Kay del termine programmazione orientata agli oggetti non contraddice questa nozione (ma di Kristen Nygaard ). Tutto ciò a cui Kay si preoccupava veramente era che tutto fosse un oggetto, e che la logica sia implementata passando messaggi tra oggetti.

Forse più interessante per la tua domanda, le classi e gli oggetti possono essere pensati in termini di funzioni e chiusure restituite dalle funzioni (che fungono da classi e costruttori contemporaneamente). Questo si avvicina molto alla programmazione basata su prototipi, e in effetti JavaScript consente di fare esattamente questo.

var cls = function (x) {
    this.y = x;
    this.fun = function () { alert(this.y); };
    return this;
};

var inst = new cls(42);
inst.fun();

(Naturalmente JavaScript consente di modificare i valori che sono illegali nella programmazione puramente funzionale, ma non è richiesto in una definizione rigorosa di OOP.)

La domanda più importante però è: Questa è una significativa classificazione di OOP? È utile considerarla come un sottoinsieme della programmazione funzionale? Penso che nella maggior parte dei casi non lo è.

    
risposta data 03.09.2012 - 14:49
fonte
6

FP come OO non è un termine ben definito. Ci sono scuole con definizioni diverse, a volte in conflitto. Se prendi in comune ciò che hanno in comune, vai a:

  • la programmazione funzionale è programmazione con funzioni di prima classe

  • La programmazione OO sta programmando con il polimorfismo di inclusione combinato con almeno una forma limitata di sovraccarico risolto dinamicamente . (Una nota a margine: in cerchi OO il polimorfismo è solitamente inteso come polimorfismo di inclusione , mentre FP è solitamente un polimorfismo parametrico . p>

Tutto il resto è presente altrove, o assente in alcuni casi.

FP e OO sono due strumenti per la creazione di astrazioni. Ognuno di essi ha i propri punti di forza e di debolezza (ad esempio, hanno una diversa direzione di estensione preferita nel problema di espressione), ma nessuno è intrinsecamente più potente dell'altro. È possibile creare un sistema OO su un kernel FP (CLOS è uno di questi sistemi). Puoi usare un framework OO per ottenere funzioni di prima classe (vedi il modo in cui le funzioni lambda sono definite in C ++ 11 per esempio).

    
risposta data 03.09.2012 - 10:42
fonte
2

No; OOP può essere visto come un superset di programmazione procedurale e differisce fondamentalmente dal paradigma funzionale perché ha lo stato rappresentato nei campi istanza. Nel paradigma funzionale le variabili sono funzioni che vengono applicate sui dati costanti per ottenere il risultato desiderato.

In realtà puoi considerare la programmazione funzionale un sottoinsieme di OOP; se rendi immutabili tutte le tue classi potresti considerare di avere qualche tipo di programmazione funzionale.

    
risposta data 03.09.2012 - 08:37
fonte
2

Risposta:

Wikipedia ha un ottimo articolo sulla programmazione funzionale con alcuni degli esempi che chiedi. @Konrad Rudolph ha già fornito il link all ' articolo OOP .

Non penso che un paradigma sia un super-set dell'altro. Sono diversi punti di vista sulla programmazione e alcuni problemi sono meglio risolti da una prospettiva e alcuni da un'altra.

La tua domanda è ulteriormente complicata da tutte le implementazioni di FP e OOP. Ogni lingua ha le sue peculiarità che sono rilevanti per ogni buona risposta alla tua domanda.

Rambling sempre più tangenziali:

Mi piace l'idea che un linguaggio come Scala cerchi di darti il meglio di entrambi i mondi. Sono preoccupato che ti dia anche le complicazioni di entrambi i mondi.

Java è un linguaggio OO, ma la versione 7 ha aggiunto una funzione "try-with-resources" che può essere utilizzata per imitare una sorta di chiusura. Qui imita l'aggiornamento di una variabile locale "a" nel mezzo di un'altra funzione, senza renderla visibile a quella funzione. In questo caso la prima metà dell'altra funzione è il costruttore ClosureTry () e la seconda metà è il metodo close ().

public class ClosureTry implements AutoCloseable {

    public static void main(String[] args) {
        int a = 1;
        try(ClosureTry ct = new ClosureTry()) {
            System.out.println("Middle Stuff...");
            a = 2;
        }
        System.out.println("a: " + a);
    }

    public ClosureTry() {
        System.out.println("Start Stuff Goes Here...");
    }

    /** Interface throws exception, but we don't have to. */
    public void close() {
        System.out.println("End Stuff Goes Here...");
    }
}

Output:

Start Stuff Goes Here...
Middle Stuff...
End Stuff Goes Here...
a: 2

Questo potrebbe essere utile per lo scopo previsto di aprire un flusso, scrivere nello stream e chiuderlo in modo affidabile, o semplicemente accoppiare due funzioni in modo da non dimenticare di chiamare il secondo dopo aver fatto qualche lavorare tra di loro. Certo, è così nuovo e insolito che un altro programmatore potrebbe rimuovere il blocco try senza rendersi conto che stanno rompendo qualcosa, quindi è attualmente un tipo di anti-pattern, ma interessante che possa essere fatto.

Puoi esprimere qualsiasi loop nella maggior parte delle lingue imperative come una ricorsione. Oggetti e variabili possono essere resi immutabili. Le procedure possono essere scritte per minimizzare gli effetti collaterali (anche se direi che una funzione vera non è possibile su un computer - il tempo necessario per l'esecuzione e il processore / disco / risorse di sistema che consuma sono effetti collaterali inevitabili). Alcuni linguaggi funzionali possono essere creati per eseguire molte, se non tutte, operazioni orientate agli oggetti. Non devono necessariamente escludersi a vicenda, sebbene alcune lingue abbiano limitazioni (come non consentire l'aggiornamento di variabili) che impediscono determinati modelli (come i campi mutabili).

Per me, le parti più utili della programmazione orientata agli oggetti sono l'occultamento dei dati (incapsulamento), il trattamento di oggetti abbastanza simili come lo stesso (polimorfismo) e la raccolta dei dati e dei metodi che operano insieme su tali dati (oggetti / classi) . L'ereditarietà può essere il fiore all'occhiello di OOP, ma per me è la parte meno importante e meno utilizzata.

Le parti più utili della programmazione funzionale sono immutabilità (token / valori anziché variabili), funzioni (senza effetti collaterali) e chiusure.

Non penso che sia orientato agli oggetti, ma devo dire che una delle cose più utili nell'informatica è la capacità di dichiarare un'interfaccia, quindi disporre di varie parti di funzionalità e dati che implementano tale interfaccia. Mi piace anche avere alcuni dati mutevoli con cui lavorare, quindi credo di non essere totalmente a mio agio in linguaggi esclusivamente funzionali, anche se provo a limitare la mutevolezza e gli effetti collaterali in tutti i miei progetti di programma.

    
risposta data 03.09.2012 - 22:46
fonte

Leggi altre domande sui tag