Orthogonalität impliziert, dass zwei Dinge nichts miteinander zu tun haben. Es kommt aus der Mathematik, wo es senkrecht bedeutet . Im allgemeinen Sprachgebrauch kann dies bedeuten, dass zwei Entscheidungen nicht miteinander zusammenhängen oder dass ein Thema für die Betrachtung eines anderen Themas irrelevant ist. Wie hier verwendet, bedeutet orthogonal, dass ein Konzept das andere weder impliziert noch ausschließt.
Die beiden Konzepte objektorientierte Programmierung und funktionale Programmierung sind nicht miteinander unvereinbar. Objektorientierung bedeutet keine Veränderlichkeit. Viele Leute, die auf herkömmliche Weise in objektorientierte Programme eingeführt werden, verwenden häufig zuerst C ++, Java, C # oder ähnliche Sprachen, in denen Mutabilität häufig vorkommt und sogar gefördert wird (Standardbibliotheken bieten eine Vielzahl von veränderlichen Klassen für Benutzer). Daher ist es verständlich, dass viele Menschen objektorientierte Programmierung mit zwingender Programmierung und Veränderlichkeit verbinden, da sie dies so gelernt haben.
Die objektorientierte Programmierung umfasst jedoch Themen wie:
- Verkapselung
- Polymorphismus
- Abstraktion
Nichts davon impliziert Veränderlichkeit, und nichts davon schließt funktionale Programmierung aus. Ja, sie sind insofern orthogonal , als sie unterschiedliche Konzepte sind. Sie sind keine Gegensätze - Sie können den einen oder den anderen oder beide (oder sogar keinen) verwenden. Sprachen wie Scala und F # versuchen, beide Paradigmen in einer einzigen Sprache zu kombinieren:
Scala ist eine Multi-Paradigma-Programmiersprache, die Funktionen der objektorientierten Programmierung und der funktionalen Programmierung integriert .
Quelle
F # ist eine prägnante, ausdrucksstarke und effiziente funktionale und objektorientierte Sprache für .NET, mit der Sie einfachen Code schreiben können, um komplexe Probleme zu lösen.
Quelle
Dies bedeutet, dass die beiden Konzepte keine gegensätzlichen Vorstellungen haben oder nicht miteinander unvereinbar sind.
Bei OO geht es um Einkapselung, Objektzusammensetzung, Datenabstraktion, Polymorphismus durch Subtypisierung und kontrollierte Mutation , falls erforderlich (Unveränderlichkeit wird auch bei OO gefördert). Bei FP geht es um Funktionszusammensetzung, Kontrollabstraktion und eingeschränkten Polymorphismus (auch bekannt als parametrischer Polymorphismus). Somit sind die beiden Ideen nicht widersprüchlich. Beide bieten Ihnen verschiedene Arten von Befugnissen und Abstraktionsmechanismen, die sicherlich in einer Sprache verfügbar sind. In der Tat ist dies die These, auf der Scala aufgebaut wurde!
In seinem Scala-Experiment- Vortrag bei Google erklärt Martin Odersky sehr gut, wie er glaubt, dass die beiden Konzepte - OO und FP - orthogonal zueinander sind und wie Scala die beiden Paradigmen elegant und nahtlos zu einem neuen Paradigma vereint, das in der Scala-Community als bekannt ist Objekt-Funktions-Paradigma. Muss zuschauen, wie du redest. :-)
Weitere Beispiele für objektfunktionale Sprachen: OCaml , F # , Nemerle .
quelle
Es bedeutet, dass sie sich nicht gegenseitig beeinflussen. Das heißt, eine funktionale Sprache ist nicht weniger funktional, weil sie auch objektorientiert ist.
Wenn sie Gegensätze wären (dh eine rein funktionale Sprache könnte unmöglich objektorientiert sein), wären sie per Definition nicht orthogonal. Ich glaube jedoch nicht, dass dies der Fall ist.
Während dies für die meisten gängigen OO-Sprachen gilt, gibt es keinen Grund, warum eine OO-Sprache einen veränderlichen Zustand haben muss.
Wenn eine Sprache Objekte, Methoden, virtuelle Vererbung und Ad-hoc-Polymorphismus aufweist, ist sie eine objektorientierte Sprache - unabhängig davon, ob sie auch einen veränderlichen Status hat oder nicht.
quelle
Wenn zwei Konzepte orthogonal sind, bedeutet dies, dass sie in jeder Manifestation in jedem Grad unabhängig voneinander verwirklicht werden können. Wenn Sie beispielsweise Musik betrachten, können Sie ein Musikstück danach klassifizieren, wie harmonisch es ist und wie rhythmisch es ist. Die beiden Begriffe "harmonisch" und "rhythmisch" sind orthogonal in dem Sinne, dass es harmonische und rhythmische Stücke gibt, disharmonische und arrythmische Stücke, aber auch disharmonische und rhythmische Stücke sowie harmonische und arrhythmische Stücke.
Auf die ursprüngliche Frage angewendet bedeutet dies, dass es rein funktionale, nicht objektorientierte Programmiersprachen wie Haskell, rein objektorientierte, "nicht funktionale" Sprachen wie Eiffel gibt, aber auch Sprachen, die weder C sind, noch Sprachen, die es sind beide wie Scala.
Einfach ausgedrückt bedeutet Scala objektorientiert, dass Sie Datenstrukturen ("Klassen" und "Merkmale") definieren können, die Daten mit den Methoden kapseln, mit denen diese Daten bearbeitet werden, um sicherzustellen, dass sich Instanzen dieser Strukturen ("Objekte") immer in a befinden definierter Zustand (der Vertrag des Objekts in seiner Klasse).
Andererseits bedeutet Scala als funktionale Sprache, dass sie unveränderliche gegenüber veränderlichen Zuständen bevorzugt und dass Funktionen erstklassige Objekte sind, die wie jedes andere Objekt als lokale Variablen, Felder oder Parameter für andere Funktionen verwendet werden können. Darüber hinaus hat fast jede Anweisung in Scala einen Wert, der Sie dazu ermutigt, einen funktionalen Programmierstil zu verwenden.
Die Orthogonalität der objektorientierten Programmierung und der funktionalen Programmierung in Scala bedeutet außerdem, dass Sie als Programmierer frei sind, eine beliebige Mischung dieser beiden Konzepte zu wählen, die Sie für Ihren Zweck für geeignet halten. Sie können Ihre Programme in einem rein imperativen Stil schreiben, indem Sie nur veränderbare Objekte verwenden und Funktionen überhaupt nicht als Objekte verwenden. Andererseits können Sie in Scala auch rein funktionale Programme schreiben, die keine der objektorientierten Funktionen verwenden.
Scala verlangt wirklich nicht, dass Sie den einen oder anderen Stil verwenden. Damit können Sie das Beste aus beiden Welten auswählen, um Ihr Problem zu lösen.
quelle
Wie bei allen Klassifikationen ist die Unterteilung der Programmiersprachen in funktionale, objektorientierte, prozedurale usw. fiktiv. Wir brauchen jedoch Klassifikationen, und in Programmiersprachen klassifizieren wir nach einer Reihe von Sprachmerkmalen und dem philosophischen Ansatz derjenigen, die die Sprache verwenden (wobei die letztere von der ersteren beeinflusst wird).
So können "objektorientierte" Sprachen manchmal erfolgreich sein, wenn sie die Merkmale und Philosophien "funktionaler" Programmiersprachen übernehmen und umgekehrt. Aber sicherlich sind nicht alle Programmiersprachenfunktionen und -philosophien kompatibel.
Beispielsweise erreicht eine funktionale Sprache wie OCaml die Kapselung durch lexikalisches Scoping und Schließen, während objektorientierte Sprachen Modifikatoren für den öffentlichen / privaten Zugriff verwenden. Dies sind per se keine inkompatiblen Mechanismen, aber sie sind redundant, und eine Sprache wie F # (eine meist funktionale Sprache, die im Einklang mit der ausgesprochen objektorientierten .NET-Bibliothek und dem Sprachstapel leben möchte) muss sich bemühen, eine Brücke zu schlagen die Lücke.
Als weiteres Beispiel verwendet OCaml ein strukturelles Typsystem zur Objektorientierung, während die meisten objektorientierten Sprachen ein nominales Typsystem verwenden. Diese sind so gut wie inkompatibel und repräsentieren interessanterweise Inkompatibilität im Bereich objektorientierter Sprachen.
quelle
Die Idee von Objekten kann unveränderlich umgesetzt werden. Ein Beispiel ist das Buch " A Theory of Objects " von Abadi und Cardelli, das darauf abzielt, diese Ideen zu formalisieren, und in dem Objekten zunächst unveränderliche Semantik gegeben wird, weil dies das Denken über objektorientierte Programme vereinfacht.
In diesem Fall gibt eine Methode, die das Objekt traditionell an Ort und Stelle geändert hätte, stattdessen ein neues Objekt zurück, während das vorherige Objekt bestehen bleibt.
quelle
Sie können Funktionen als Objekte und Objekte als Sammlungen von Funktionen implementieren, sodass eindeutig eine Beziehung zwischen den beiden Konzepten besteht.
Sie sprechen von einer rein funktionalen Programmierung.
Objekte müssen nicht veränderbar sein. Ich würde sagen, dass Objekte und Mutationen orthogonale Konzepte waren. Beispielsweise bietet die Programmiersprache OCaml eine Syntax für die rein funktionale Objektaktualisierung.
Nicht wirklich. Das Fehlen einer Tail-Call-Optimierung bedeutet, dass der Großteil des idiomatischen rein funktionalen Codes in Scala einen Stapelüberlauf aufweist, da dadurch Stapelrahmen verloren gehen. Zum Beispiel der Continuation Passing Style (CPS) und alle Techniken, die in dem Artikel That about von Bruce McAdam beschrieben werden. Es gibt keine einfache Möglichkeit, dies zu beheben, da die JVM selbst keine Tail-Call-Optimierung durchführen kann.
In Bezug auf die Orthogonalität der rein funktionalen Programmierung und der objektorientierten Programmierung würde ich sagen, dass sie zumindest nahezu orthogonal sind, nur weil sich die rein funktionale Programmierung nur mit Programmen in kleinen (z. B. Funktionen höherer Ordnung) befasst, während sich die objektorientierte Programmierung mit großen befasst -skalierte Strukturierung von Programmen. Aus diesem Grund bieten funktionale Programmiersprachen normalerweise einen anderen Mechanismus für die Strukturierung in großem Maßstab, z. B. die Modulsysteme höherer Ordnung von Standard ML und OCaml oder CLOS für Common Lisp oder Typklassen für Haskell.
quelle
Eine Sache, die mir geholfen hat, die Beziehung zwischen FP und OO zu verstehen, war das SICP-Buch, insbesondere der Abschnitt "Modularität von Funktionsprogrammen und Modularität von Objekten". Wenn Sie über diese Probleme nachdenken und ein freies Wochenende haben, lohnt es sich möglicherweise, sie durchzulesen die ersten drei Kapitel, seine hübsche Augenöffnung.
quelle
Ich habe gerade eine wunderbare Erklärung gefunden für die Orthogonalität von OOP und FP gefunden.
Die Grundidee ist wie folgt. Stellen Sie sich vor, wir arbeiten mit ASTs von mathematischen Ausdrücken. Wir haben also verschiedene Arten von Substantiven (Konstante, Addition, Multiplikation) und verschiedene Verben (eval, toString).
Sagen wir, der Ausdruck ist
(1 + 2) * 3
. Dann wäre der AST:Um ein Verb zu implementieren, müssen wir seine Implementierung für jede Art von Substantiv bereitstellen. Wir können es als Tabelle darstellen:
+---------------------+-------------------------------------+ | eval | toString | +---------------+---------------------+-------------------------------------+ | constant | value | value.toString | +---------------+---------------------+-------------------------------------+ | addition | lhs.eval + rhs.eval | lhs.toString + " + " + rhs.toString | +---------------+---------------------+-------------------------------------+ | mutiplication | lhs.eval * rhs.eval | lhs.toString + " * " + rhs.toString | +---------------+---------------------+-------------------------------------+
Die „Orthogonalität“ ergibt sich aus der Tatsache, dass wir diese Tabelle in OOP zeilenweise implementieren werden : Wir werden jedes Substantiv als Klasse darstellen, die jede Methode implementieren muss.
In FP hingegen implementieren wir diese Tabelle nach Spalten - wir schreiben für jedes Verb eine Funktion, und diese Funktion reagiert unterschiedlich auf Argumente unterschiedlichen Typs (wahrscheinlich unter Verwendung des Mustervergleichs).
quelle
Senkrecht. Es klingt gut. Wenn Sie eine Ausbildung haben, können Sie sie ein wenig binden und so tun, als ob. Es ist ein bisschen wie ein Paradigma.
Es hängt alles davon ab, in welchen Kreisen Sie reisen und welche Art von Programmiertechnik Sie erhalten. Ich habe ein paar Beiträge über SS gelesen und die meisten, die aus einer funktionalen Programmiersprache stammen, bestehen weiterhin darauf, dass man nur funktional werden kann und alles andere gegen das Denken und die Denkweise verstößt.
Bei der objektorientierten Programmierung geht es hauptsächlich darum, den Status zu erfassen und diesen Status so lokal wie möglich zu halten, damit er nicht von etwas beeinflusst wird, das nicht Teil des Objekts ist, mit dem Sie den Status verwalten. Andererseits betrachtet die funktionale Programmierung das Problem des Zustands aus einer anderen Perspektive und versucht, den Zustand vom System zu trennen und auf Funktionen zu reduzieren. Ja, Sie können beide Techniken in Ihrem Code verwenden, aber beide betrachten das Design von Software aus verschiedenen Blickwinkeln.
Es gab großes Interesse an den Techniken der funktionalen Programmierung, hauptsächlich wegen des vom Staat geforderten Managements beim Umgang mit Mehrkernchips und paralleler Programmierung. Zu diesem Zeitpunkt scheint die funktionale Programmierung die Oberhand zu haben, aber Sie können den gleichen Effekt mit Objekten erzielen. Sie denken nur anders über das Problem. Anstatt sich am Kopf zu kratzen und zu versuchen, den Zustand so weit wie möglich loszuwerden, sehen Sie sich Objekte im Design an und sehen, wie Sie sie mithilfe von Designmustern, CRC und dem Kern dessen koppeln können, was von ihnen erwartet wird Objektanalyse. Wo Objekte jedoch zu ihren eigenen gehören und wo funktionale Programmierung viel schwieriger ist, besteht darin, die reale Welt zu analysieren und sie einem verständlichen Computersystem zuzuordnen. In OO zum Beispiel Ein Personenobjekt wäre eine Verkapselung des Zustands mit Methoden, die auf den Personenzustand einwirken. Bei der funktionalen Programmierung würde eine Person in Datenteile und Funktionen zerlegt, die auf die Personendaten einwirken, mit der zusätzlichen Maßgabe, dass Daten einmal und nur einmal erstellt und unveränderlich sein sollten.
Ich muss zugeben, obwohl ich aus einem OO-Hintergrund stamme, dass ich in den meisten OO-Sprachen beim Umgang mit Multi-Core-Chips den funktionalen Weg gegangen bin, hauptsächlich durch Designstrukturen für die Kernprogrammierung (wie Threads und Delegaten) und Pseudodatenobjekte herumgereicht habe. Dies hat mich dazu gebracht, die Techniken der OO-Programmierung in Frage zu stellen, da sie diesem Thread-Design nicht gut zu entsprechen scheint.
quelle