Plus je fais de programmation fonctionnelle, plus j'ai l'impression qu'il ajoute une couche d'abstraction supplémentaire qui ressemble à la couche d'un oignon - englobant toutes les couches précédentes.
Je ne sais pas si cela est vrai, alors en dérogeant aux principes de POO avec lesquels je travaille depuis des années, quelqu'un peut-il expliquer comment fonctionnel décrit ou non avec précision l'un d'entre eux: encapsulation, abstraction, héritage, polymorphisme
Je pense que nous pouvons tous dire, oui, il a une encapsulation via des tuples, ou les tuples comptent-ils techniquement comme un fait de "programmation fonctionnelle" ou sont-ils simplement une utilité du langage?
Je sais que Haskell peut répondre à l'exigence d '"interfaces", mais encore une fois pas certain si sa méthode est un fait fonctionnel? Je suppose que le fait que les foncteurs aient une base mathématique pourrait-on dire que ceux-ci sont définitivement définis dans l'attente de la fonctionnalité, peut-être?
Veuillez décrire en détail comment vous pensez que la fonctionnalité répond ou non aux 4 principes de la POO.
Edit: Je comprends très bien les différences entre le paradigme fonctionnel et le paradigme orienté objet et je réalise qu'il y a beaucoup de langages multiparadigmes de nos jours qui peuvent faire les deux. Je suis vraiment à la recherche de définitions de la façon dont fp (pensez puriste, comme haskell) peut faire l'une des 4 choses énumérées, ou pourquoi il ne peut pas en faire. c.-à-d. "L'encapsulation peut se faire avec des fermetures" (ou si je me trompe dans cette croyance, veuillez expliquer pourquoi).
la source
Réponses:
La programmation fonctionnelle n'est pas une couche au-dessus de la POO; c'est un paradigme complètement différent. Il est possible de faire de la POO dans un style fonctionnel (F # a été écrit exactement dans ce but), et à l'autre bout du spectre, vous avez des trucs comme Haskell, qui rejette explicitement les principes d'orientation des objets.
Vous pouvez effectuer l'encapsulation et l'abstraction dans n'importe quel langage suffisamment avancé pour prendre en charge les modules et les fonctions. OO fournit des mécanismes spéciaux pour l'encapsulation, mais ce n'est pas quelque chose d'inhérent à OO. Le point d'OO est la deuxième paire que vous avez mentionnée: l'hérédité et le polymorphisme. Le concept est officiellement connu sous le nom de substitution Liskov, et vous ne pouvez pas l'obtenir sans la prise en charge au niveau du langage pour la programmation orientée objet. (Oui, il est possible de le simuler dans certains cas, mais vous perdez beaucoup des avantages qu'OO apporte à la table.)
La programmation fonctionnelle ne se concentre pas sur la substitution Liskov. Il se concentre sur l'augmentation du niveau d'abstraction et sur la minimisation de l'utilisation de l'état mutable et de routines avec des "effets secondaires", qui est un terme que les programmeurs fonctionnels aiment utiliser pour créer des routines qui font réellement quelque chose (par opposition à simplement calculer quelque chose). effrayant. Mais encore une fois, ce sont des paradigmes complètement séparés, qui peuvent être utilisés ensemble ou non, selon le langage et les compétences du programmeur.
la source
Je trouve l'intuition suivante utile pour comparer OOP et FP.
Plutôt que de considérer FP comme un surensemble de la POO, pensez à la POO et à la FP comme deux façons alternatives d'examiner un modèle de calcul sous-jacent similaire dans lequel vous avez:
Dans la POO, cela est capturé par
Dans FP, cela est capturé par
Avec cette interprétation, un objet peut être vu comme une collection de fermetures (ses méthodes) capturant toutes les mêmes variables non locales (les variables membres de l'objet communes à toutes les fermetures de la collection). Cette vue est également soutenue par le fait que dans les langages orientés objet, les fermetures sont souvent modélisées comme des objets avec exactement une méthode.
Je pense que les différents points de vue proviennent du fait que la vue orientée objet est centrée sur les objets (les données) tandis que la vue fonctionnelle est centrée sur les fonctions / fermetures (les opérations).
la source
Cela dépend de qui vous demandez une définition de la POO. Demandez à cinq personnes et vous obtiendrez probablement six définitions. Wikipédia dit :
Donc, chaque fois que quelqu'un donne une réponse très définitive, prenez-la avec un grain de sel.
Cela dit, il y a un bon argument à faire valoir que, oui, FP est un surensemble de POO en tant que paradigme. En particulier, la définition d'Alan Kay du terme programmation orientée objet ne contredit pas cette notion (mais celle de Kristen Nygaard ). Tout ce qui préoccupait Kay était que tout est un objet, et que la logique est mise en œuvre en passant des messages entre les objets.
Peut-être plus intéressant pour votre question, les classes et les objets peuvent être considérés en termes de fonctions et de fermetures renvoyées par les fonctions (qui agissent à la fois comme classes et constructeurs). Cela est très proche de la programmation basée sur des prototypes, et en fait, JavaScript permet de le faire précisément.
(Bien sûr, JavaScript permet la mutation de valeurs, ce qui est illégal dans la programmation purement fonctionnelle, mais il n'est pas non plus requis dans une définition stricte de la POO.)
La question la plus importante est cependant: est-ce une classification significative de la POO? Est-il utile de le considérer comme un sous-ensemble de programmation fonctionnelle? Je pense que dans la plupart des cas, ce n'est pas le cas.
la source
FP comme OO n'est pas un terme bien défini. Il existe des écoles aux définitions différentes, parfois contradictoires. Si vous prenez ce qu'ils ont en commun, vous vous mettez à:
la programmation fonctionnelle est la programmation avec des fonctions de première classe
La programmation OO est une programmation avec polymorphisme d'inclusion combiné avec au moins une forme restreinte de surcharge résolue dynamiquement. (Remarque: dans les cercles OO, le polymorphisme est généralement considéré comme le polymorphisme d' inclusion , tandis que dans les écoles FP, il signifie généralement le polymorphisme paramétrique .)
Tout le reste est soit présent ailleurs, soit absent dans certains cas.
FP et OO sont deux outils de construction d'abstractions. Ils ont chacun leurs propres forces et faiblesses (par exemple, ils ont une direction d'extension préférée différente dans le problème d'expression), mais aucune n'est intrinsèquement plus puissante que l'autre. Vous pouvez construire un système OO sur un noyau FP (CLOS en est un). Vous pouvez utiliser un framework OO pour obtenir des fonctions de première classe (voir la façon dont les fonctions lambda sont définies en C ++ 11 par exemple).
la source
std::function
, auquel des pointeurs de fonction et des lambdas peuvent être attribués, est décidément générique et non orienté objet. Ce n'est pas une surprise, car la marque limitée de polymorphisme orientée objet (polymorphisme de sous-type) est strictement moins puissante que le polymorphisme paramétrique (même Hindley-Milner, et encore moins le système complet F-oméga).Non; La POO peut être considérée comme un surensemble de programmation procédurale et diffère fondamentalement du paradigme fonctionnel car elle a un état représenté dans les champs d'instance. Dans le paradigme fonctionnel, les variables sont des fonctions qui sont appliquées aux données constantes afin d'obtenir le résultat souhaité.
En fait, vous pouvez considérer la programmation fonctionnelle comme un sous-ensemble de POO; si vous rendez toutes vos classes immuables, vous pouvez considérer que vous avez une sorte de programmation fonctionnelle.
la source
Répondre:
Wikipedia a un excellent article sur la programmation fonctionnelle avec certains des exemples que vous demandez. @Konrad Rudolph a déjà fourni le lien vers l' article OOP .
Je ne pense pas qu'un paradigme soit un super-ensemble de l'autre. Ce sont des perspectives différentes sur la programmation et certains problèmes sont mieux résolus d'un point de vue et certains d'un autre.
Votre question est encore compliquée par toutes les implémentations de FP et OOP. Chaque langue a ses propres bizarreries qui sont pertinentes pour toute bonne réponse à votre question.
Randonnée de plus en plus tangentielle:
J'aime l'idée qu'une langue comme Scala essaie de vous donner le meilleur des deux mondes. Je crains que cela ne vous donne aussi les complications des deux mondes.
Java est un langage OO, mais la version 7 a ajouté une fonctionnalité "essayer avec des ressources" qui peut être utilisée pour imiter une sorte de fermeture. Ici, il imite la mise à jour d'une variable locale "a" au milieu d'une autre fonction, sans la rendre visible pour cette fonction. Dans ce cas, la première moitié de l'autre fonction est le constructeur ClosureTry () et la seconde moitié est la méthode close ().
Sortie:
Cela peut être utile pour son objectif prévu d'ouvrir un flux, d'écrire dans le flux et de le fermer de manière fiable, ou pour simplement associer deux fonctions d'une manière que vous n'oubliez pas d'appeler la seconde après avoir effectué un travail entre elles . Bien sûr, c'est tellement nouveau et inhabituel qu'un autre programmeur peut supprimer le bloc try sans se rendre compte qu'ils cassent quelque chose, c'est donc actuellement une sorte d'anti-pattern, mais intéressant que cela puisse être fait.
Vous pouvez exprimer n'importe quelle boucle dans la plupart des langues impératives comme une récursivité. Les objets et les variables peuvent être rendus immuables. Des procédures peuvent être écrites pour minimiser les effets secondaires (même si je dirais qu'une véritable fonction n'est pas possible sur un ordinateur - le temps qu'il faut pour exécuter et les ressources processeur / disque / système qu'il consomme sont des effets secondaires inévitables). Certains langages fonctionnels peuvent être conçus pour effectuer de nombreuses, sinon toutes, les opérations orientées objet. Ils ne doivent pas être mutuellement exclusifs, bien que certaines langues aient des limitations (comme interdire toute mise à jour des variables) qui empêchent certains modèles (comme les champs mutables).
Pour moi, les parties les plus utiles de la programmation orientée objet sont le masquage des données (encapsulation), le traitement d'objets suffisamment similaires comme les mêmes (polymorphisme) et la collecte de vos données et méthodes qui opèrent ensemble sur ces données (objets / classes). L'héritage est peut-être le fleuron de la POO, mais pour moi, c'est la partie la moins importante et la moins utilisée.
Les parties les plus utiles de la programmation fonctionnelle sont l'immuabilité (jetons / valeurs au lieu de variables), les fonctions (pas d'effets secondaires) et les fermetures.
Je ne pense pas que ce soit orienté objet, mais je dois dire que l'une des choses les plus utiles en informatique est la capacité de déclarer une interface, puis de disposer de diverses fonctionnalités et données pour implémenter cette interface. J'aime également avoir quelques données mutables avec lesquelles travailler, donc je suppose que je ne suis pas totalement à l'aise dans les langages exclusivement fonctionnels, même si j'essaie de limiter la mutabilité et les effets secondaires dans toutes mes conceptions de programmes.
la source