Funktionale Programmierung im Vergleich zu OOP mit Klassen


32

Ich habe mich in letzter Zeit für einige Konzepte der funktionalen Programmierung interessiert. Ich benutze OOP seit einiger Zeit. Ich kann sehen, wie ich eine ziemlich komplexe App in OOP erstellen würde. Jedes Objekt würde wissen, wie man Dinge tut, die dieses Objekt tut. Oder was auch immer die Elternklasse macht. Also kann ich einfach sagen Person().speak(), dass ich die Person zum Reden bringen soll.

Aber wie mache ich ähnliche Dinge in der funktionalen Programmierung? Ich sehe, wie Funktionen erstklassige Gegenstände sind. Aber diese Funktion macht nur eine bestimmte Sache. Hätte ich einfach eine say()Methode im Umlauf und würde sie mit einer Entsprechung von Person()Argumenten bezeichnen, damit ich weiß, was etwas aussagt?

Ich kann also die einfachen Dinge sehen, wie würde ich die Vergleichbarkeit von OOP und Objekten in der funktionalen Programmierung herstellen, um meine Codebasis zu modularisieren und zu organisieren?

Als Referenz habe ich hauptsächlich Erfahrung mit OOP mit Python, PHP und etwas C #. Die Sprachen, die ich betrachte, die Funktionsmerkmale haben, sind Scala und Haskell. Obwohl ich mich zu Scala neige.

Grundlegendes Beispiel (Python):

Animal(object):
    def say(self, what):
        print(what)

Dog(Animal):
    def say(self, what):
        super().say('dog barks: {0}'.format(what))

Cat(Animal):
    def say(self, what):
        super().say('cat meows: {0}'.format(what))

dog = Dog()
cat = Cat()
dog.say('ruff')
cat.say('purr')

Scala ist als OOP + FP konzipiert, so dass Sie nicht wählen müssen
Karthik T

1
Ja, ich bin mir bewusst, aber ich möchte es auch aus intellektuellen Gründen wissen. Ich kann nichts auf dem Äquivalent von Objekt in funktionalen Sprachen finden. Wie für Scala würde ich immer noch wissen wollen, wann / wo / wie ich funktional über oop verwenden sollte, aber das IMHO ist eine andere Frage.
Skift

2
"Besonders überbetont ist IMO die Vorstellung, dass wir den Staat nicht aufrechterhalten.": Dies ist die falsche Vorstellung. Es ist nicht wahr, dass FP state nicht verwendet, vielmehr behandelt FP state auf andere Weise (z. B. Monaden in Haskell oder eindeutige Typen in Clean).
Giorgio


3
mögliches Duplikat von Functional Programming vs. OOP
Caleb

Antworten:


21

Was Sie hier wirklich fragen, ist, wie Sie Polymorphismus in funktionalen Sprachen ausführen , dh wie Sie Funktionen erstellen, die sich aufgrund ihrer Argumente unterschiedlich verhalten.

Beachten Sie, dass das erste Argument für eine Funktion in der Regel dem "Objekt" in OOP entspricht, in funktionalen Sprachen jedoch normalerweise Funktionen von Daten getrennt werden sollen, sodass es sich bei dem "Objekt" wahrscheinlich um einen reinen (unveränderlichen) Datenwert handelt.

Funktionssprachen bieten im Allgemeinen verschiedene Möglichkeiten, um Polymorphismus zu erreichen:

  • So etwas wie Multimethoden, die eine andere Funktion aufrufen, indem sie die angegebenen Argumente untersuchen. Dies kann für den Typ des ersten Arguments erfolgen (was praktisch dem Verhalten der meisten OOP-Sprachen entspricht), kann jedoch auch für andere Attribute der Argumente erfolgen.
  • Prototyp / objektähnliche Datenstrukturen, die erstklassige Funktionen als Mitglieder enthalten . So können Sie eine Mitsprachefunktion in Ihre Hunde- und Katzendatenstrukturen einbetten. Tatsächlich haben Sie den Code zum Teil der Daten gemacht.
  • Pattern Matching - wobei die Pattern Matching-Logik in die Funktionsdefinition integriert ist und unterschiedliche Verhaltensweisen für unterschiedliche Parameter sicherstellt. Häufig in Haskell.
  • Branching / conditions - Entspricht den if / else-Klauseln in OOP. Ist möglicherweise nicht hochgradig erweiterbar, kann aber in vielen Fällen sinnvoll sein, wenn Sie eine begrenzte Anzahl möglicher Werte haben (z. B. wurde der Funktion eine Zahl oder eine Zeichenfolge oder eine Null übergeben?)

Im Folgenden finden Sie ein Beispiel für eine Clojure-Implementierung Ihres Problems mit mehreren Methoden:

;; define a multimethod, that dispatched on the ":type" keyword
(defmulti say :type)  

;; define specific methods for each possible value of :type. You can add more later
(defmethod say :cat [animal what] (println (str "Car purrs: " what)))
(defmethod say :dog [animal what] (println (str "Dog barks: " what)))
(defmethod say :default [animal what] (println (str "Unknown noise: " what)))

(say {:type :dog} "ruff")
=> Dog barks: ruff

(say {:type :ape} "ook")
=> Unknown noise: ook

Beachten Sie, dass für dieses Verhalten keine expliziten Klassen definiert werden müssen: Reguläre Maps funktionieren einwandfrei. Die Dispatch-Funktion (in diesem Fall: type) kann eine beliebige Funktion der Argumente sein.


Nicht 100% klar, aber genug, um zu sehen, wohin Sie gehen. Ich könnte dies als den 'Tier'-Code in einer bestimmten Datei sehen. Auch der Teil über Verzweigungen / Bedingungen ist gut. Ich hatte das nicht als Alternative zu if / else angesehen.
Skift

11

Dies ist keine direkte Antwort und auch nicht unbedingt 100% genau, da ich kein Experte für funktionale Sprachen bin. Aber in jedem Fall werde ich meine Erfahrung mit Ihnen teilen ...

Vor ungefähr einem Jahr war ich in einem ähnlichen Boot wie Sie. Ich habe C ++ und C # gemacht und alle meine Designs waren immer sehr schwer auf OOP. Ich habe von FP-Sprachen gehört, online einige Informationen gelesen, das F # -Buch durchgesehen, konnte aber immer noch nicht wirklich verstehen, wie eine FP-Sprache OOP ersetzen oder allgemein nützlich sein kann, da die meisten Beispiele, die ich gesehen habe, einfach zu einfach waren.

Für mich kam der "Durchbruch", als ich mich entschied, Python zu lernen. Ich habe Python heruntergeladen, bin dann zur Projekt-Euler-Homepage gegangen und habe gerade angefangen, ein Problem nach dem anderen zu lösen. Python ist nicht unbedingt eine FP-Sprache, und Sie können durchaus Klassen darin erstellen, aber im Vergleich zu C ++ / Java / C # enthält es viel mehr FP-Konstrukte. Als ich anfing, damit zu spielen, traf ich die bewusste Entscheidung, dies nicht zu tun Definieren Sie eine Klasse, es sei denn, ich musste unbedingt.

Was ich an Python interessant fand, war, wie einfach und natürlich es war, Funktionen zu übernehmen und sie zu "nähen", um komplexere Funktionen zu erstellen, und am Ende wurde Ihr Problem immer noch durch Aufrufen einer einzelnen Funktion gelöst.

Sie haben darauf hingewiesen, dass Sie beim Codieren das Prinzip der alleinigen Verantwortung befolgen sollten, und das ist absolut richtig. Nur weil die Funktion für eine einzelne Aufgabe verantwortlich ist, bedeutet dies nicht, dass sie nur das absolute Minimum leisten kann. In FP haben Sie noch Abstraktionsstufen. So können Ihre übergeordneten Funktionen immer noch "eins" tun, aber sie können Funktionen auf untergeordnete Ebenen delegieren, um genauere Details darüber zu implementieren, wie diese "eine" Sache erreicht wird.

Der Schlüssel zu FP ist jedoch, dass Sie keine Nebenwirkungen haben. Solange Sie die Anwendung als einfache Datentransformation mit definierten Eingaben und Ausgaben behandeln, können Sie FP-Code schreiben, der genau das leistet, was Sie benötigen. Natürlich passt nicht jede Anwendung gut in diese Form, aber sobald Sie damit beginnen, werden Sie überrascht sein, wie viele Anwendungen passen. Und hier scheinen meiner Meinung nach Python, F # oder Scala zu glänzen, weil sie Ihnen FP-Konstrukte liefern, aber wenn Sie sich an Ihren Zustand erinnern und Nebenwirkungen einführen müssen, können Sie immer auf echte und erprobte OOP-Techniken zurückgreifen.

Seitdem habe ich eine ganze Reihe von Python-Code als Hilfsprogramme und andere Hilfsskripte für die interne Arbeit geschrieben, und einige davon sind ziemlich weit fortgeschritten, aber durch das Erinnern an grundlegende SOLID-Prinzipien ist der größte Teil des Codes immer noch sehr wartbar und flexibel. Genau wie in OOP ist Ihre Schnittstelle eine Klasse und Sie verschieben Klassen, wenn Sie Funktionen umgestalten und / oder hinzufügen. In FP machen Sie genau dasselbe mit Funktionen.

Letzte Woche habe ich angefangen, in Java zu programmieren, und seitdem werde ich fast täglich daran erinnert, dass ich in OOP Interfaces implementieren muss, indem ich Klassen mit Methoden deklariere, die Funktionen überschreiben. In einigen Fällen konnte ich dasselbe in Python mit a erreichen Ein einfacher Lambda-Ausdruck, zum Beispiel 20-30 Zeilen Code, die ich geschrieben habe, um ein Verzeichnis zu durchsuchen, wären in Python 1-2 Zeilen und keine Klassen gewesen.

FP selbst sind höhere Sprachen. In Python (sorry, meine einzige FP-Erfahrung) könnte ich das Listenverständnis in ein anderes Listenverständnis mit Lambdas und anderem eingeworfenen Material einfügen, und das Ganze würde nur 3-4 Codezeilen umfassen. In C ++ könnte ich genau dasselbe erreichen, aber da C ++ eine niedrigere Version ist, müsste ich viel mehr Code als 3-4 Zeilen schreiben und mit zunehmender Anzahl der Zeilen würde mein SRP-Training beginnen Überlegen Sie, wie Sie den Code in kleinere Teile aufteilen (dh mehr Funktionen). Aber im Interesse der Wartbarkeit und des Versteckens von Implementierungsdetails würde ich all diese Funktionen in dieselbe Klasse einordnen und privat machen. Und da haben Sie es ... Ich habe gerade eine Klasse erstellt, während ich in Python "return (.... lambda x: .. ....)" geschrieben hätte.


Ja, es beantwortet die Frage nicht direkt, aber dennoch eine großartige Antwort. Wenn ich kleinere Skripte oder Pakete in Python schreibe, verwende ich auch nicht immer Klassen. Oft passt es perfekt, es nur in einem Paketformat zu haben. Besonders wenn ich keinen Staat brauche. Ich stimme auch zu, dass Listenverständnisse ebenfalls verdammt nützlich sind. Seit ich über FP gelesen habe, habe ich gemerkt, wie viel mächtiger sie sein können. Das hat mich dazu gebracht, mehr über FP im Vergleich zu OOP zu erfahren.
Skift

Gute Antwort. Spreche zu jedem stehend auf der Seite der funcctional Pool , aber nicht sicher , ob ihren Zehen ins Wasser zu tauchen
Robben_Ford_Fan_boy

Und Ruby ... Eine seiner Designphilosophien konzentriert sich auf Methoden, die einen Codeblock als Argument verwenden, normalerweise einen optionalen. Und angesichts der sauberen Syntax ist das Denken und Codieren auf diese Weise einfach. In C # ist es schwer, so zu denken und zu komponieren. C # writ ist funktional ausführlich und desorientiert, es fühlt sich in die Sprache eingebunden. Ich finde es gut, dass Ruby dabei geholfen hat, funktionell einfacher zu denken und das Potenzial in meiner C # -Denkbox zu erkennen. Letztendlich sehe ich funktional und OO als komplementär; Ich würde sagen, Ruby glaubt das mit Sicherheit.
Radarbob

8

In Haskell haben Sie am nächsten "Klasse". Diese Klasse ist zwar nicht mit der Klasse in Java und C ++ identisch , funktioniert aber in diesem Fall für das, was Sie möchten.

In Ihrem Fall sieht Ihr Code so aus.

Klasse Tier ein wo 
say :: String -> sound 

Dann können Sie einzelne Datentypen haben, die diese Methoden anpassen.

Beispiel Tier Hund wo
sag s = "bark" ++ s 

BEARBEITEN: - Bevor Sie sich auf Hund spezialisieren können, müssen Sie dem System mitteilen, dass Hund ein Tier ist.

Daten Hund = \ - etwas hier - \ (Tier ableiten)

EDIT: - Für Wilq.
Wenn Sie say in einer Funktion say foo verwenden möchten, müssen Sie haskell mitteilen, dass foo nur mit Animal arbeiten kann.

foo :: (Tier a) => a -> String -> String
foo a str = sag einen str 

Wenn du jetzt mit Hund foo rufst, bellt es, wenn du mit Katze rufst, miaut es.

main = do 
let d = dog (\ - cstr parameters - \)
    c = kat  
in Show $ foo d "Hallo Welt"

Sie können jetzt keine andere Definition der Funktion sagen. Wenn say mit etwas aufgerufen wird, das kein Tier ist, verursacht es einen Kompilierungsfehler.


Ich muss ein bisschen mehr über haskell erfahren, um das vollständig zu verstehen, aber ich glaube, ich verstehe es. Ich bin immer noch neugierig, wie sich dies mit einer komplexeren Codebasis arrangieren würde.
Skift

Nitpick Animal sollte in Großbuchstaben geschrieben werden
Daniel Gratzer

1
Woher weiß die say-Funktion, dass Sie es für einen Hund aufrufen, wenn es nur eine Zeichenfolge nimmt? Und "ableiten" ist nicht nur für einige eingebaute Klassen?
WilQu

6

Funktionale Sprachen verwenden zwei Konstrukte, um Polymorphismus zu erreichen:

  • Funktionen erster Ordnung
  • Generika

Das Erstellen von polymorphem Code mit diesen unterscheidet sich grundlegend von der Verwendung von Vererbung und virtuellen Methoden in OOP. Während beide möglicherweise in Ihrer bevorzugten OOP-Sprache (wie C #) verfügbar sind, setzen die meisten funktionalen Sprachen (wie Haskell) auf elf. Es kommt selten vor, dass Funktionen nicht generisch sind, und die meisten Funktionen haben Funktionen als Parameter.

Es ist schwer so zu erklären und es wird viel Zeit in Anspruch nehmen, diesen neuen Weg zu lernen. Aber um dies zu tun, müssen Sie OOP komplett vergessen, da dies in der funktionalen Welt nicht funktioniert.


2
OOP dreht sich alles um Polymorphismus. Wenn Sie der Meinung sind, dass bei OOP Funktionen mit Ihren Daten verknüpft sind, wissen Sie nichts über OOP.
Euphoric

4
Polymorphismus ist nur ein Aspekt von OOP, und ich denke nicht der, nach dem die OP wirklich fragt.
Doc Brown

2
Polymorphismus ist ein Schlüsselaspekt von OOP. Alles andere ist da, um es zu unterstützen. OOP ohne Vererbung / virtuelle Methoden entspricht fast genau der prozeduralen Programmierung.
Euphoric

1
@ErikReppen Wenn "Apply a Interface" nicht oft benötigt wird, dann machen Sie kein OOP. Haskell hat auch Module.
Euphorischer

1
Sie brauchen nicht immer eine Schnittstelle. Aber sie sind sehr nützlich, wenn Sie sie brauchen. Und IMO ein weiterer wichtiger Teil von OOP. Was die Module in Haskell angeht, ist dies meiner Meinung nach in Bezug auf die Code-Organisation der OOP für funktionale Sprachen am nächsten. Zumindest von dem, was ich bisher gelesen habe. Ich weiß, dass sie immer noch sehr unterschiedlich sind.
Skift

0

Es hängt wirklich davon ab, was Sie erreichen wollen.

Wenn Sie nur eine Möglichkeit zum Organisieren des Verhaltens anhand ausgewählter Kriterien benötigen, können Sie z. B. ein Wörterbuch (Hash-Tabelle) mit Funktionsobjekten verwenden. In Python könnte es etwa so aussehen:

def bark(what):
    print "barks: {0}".format(what) 

def meow(what):
    print "meows: {0}".format(what)

def climb(how):
    print "climbs: {0}".format(how)

if __name__ == "__main__":
    animals = {'dog': {'say': bark},
               'cat': {'say': meow,
                       'climb': climb}}
    animals['dog']['say']("ruff")
    animals['cat']['say']("purr")
    animals['cat']['climb']("well")

Beachten Sie jedoch, dass (a) es keine "Fälle" von Hund oder Katze gibt und (b) Sie den "Typ" Ihrer Objekte selbst nachverfolgen müssen.

wie zum Beispiel: pets = [['martin','dog','grrrh'], ['martha', 'cat', 'zzzz']]. dann könntest du so ein Listenverständnis machen[animals[pet[1]]['say'](pet[2]) for pet in pets]


0

OO-Sprachen können anstelle von einfachen Sprachen verwendet werden, um eine direkte Verbindung mit einer Maschine herzustellen. C ++ Sicher, aber auch für C # gibt es Adapter und dergleichen. Das Schreiben von Code zur Steuerung mechanischer Teile und die minutiöse Steuerung des Speichers sollten jedoch so niedrig wie möglich gehalten werden. Aber wenn diese Frage mit aktueller objektorientierter Software wie Line Of Business, Webanwendungen, IOT, Webdiensten und den meisten Massenanwendungen zusammenhängt, dann ...

Antworten Sie gegebenenfalls

Leser können versuchen, mit einer serviceorientierten Architektur (SOA) zu arbeiten. Das heißt, DDD, N-Layered, N-Tiered, Hexagonal, was auch immer. Ich habe noch keine Large Business-Anwendung gesehen, die "traditionelle" OO (Active-Record oder Rich-Models) effizient einsetzt, wie es in den 70er und 80er Jahren im letzten Jahrzehnt beschrieben wurde. (Siehe Anmerkung 1)

Der Fehler liegt nicht am OP, aber es gibt ein paar Probleme mit der Frage.

  1. Das Beispiel, das Sie zur Verfügung stellen, soll lediglich den Polymorphismus demonstrieren, es handelt sich nicht um Produktionscode. Manchmal werden genau solche Beispiele wörtlich genommen.

  2. In FP und SOA werden Daten von Business Logic getrennt. Das heißt, Daten und Logik gehören nicht zusammen. Die Logik bezieht sich auf Dienste, und Daten (Domänenmodelle) weisen kein polymorphes Verhalten auf (siehe Hinweis 2).

  3. Dienste und Funktionen können polymorph sein. In FP übergeben Sie häufig Funktionen als Parameter anstelle von Werten an andere Funktionen. Sie können dasselbe in OO Languages ​​mit Typen wie Callable oder Func tun, aber es wird nicht zügellos ausgeführt (siehe Hinweis 3). In FP und SOA sind Ihre Modelle nicht polymorph, sondern nur Ihre Dienste / Funktionen. (Siehe Anmerkung 4)

  4. In diesem Beispiel gibt es einen schlechten Fall der Hardcodierung. Ich spreche nicht nur von der roten Schnur "Hundebellen". Ich spreche auch über das CatModel und DogModel selbst. Was passiert, wenn Sie ein Schaf hinzufügen möchten? Sie müssen in Ihren Code gehen und neuen Code erstellen? Warum? Im Produktionscode würde ich eher nur ein AnimalModel mit seinen Eigenschaften sehen. Im schlimmsten Fall ein AmphibienModell und ein GeflügelModell, wenn ihre Eigenschaften und Handhabung so unterschiedlich sind.

Dies ist, was ich in einer aktuellen "OO" -Sprache erwarten würde:

public class Animal
{
    public int AnimalID { get; set; }
    public int LegCount { get; set; }
    public string Name { get; set; }
    public string WhatISay { get; set; }
}

public class AnimalService : IManageAnimals
{
    private IPersistAnimals _animalRepo;
    public AnimalService(IPersistAnimals animalRepo) { _animalRepo = animalRepo; }

    public List<Animal> GetAnimals() => _animalRepo.GetAnimals();

    public string WhatDoISay(Animal animal)
    {
        if (!string.IsNullOrWhiteSpace(animal.WhatISay))
            return animal.WhatISay;

        return _animalRepo.GetAnimalNoise(animal.AnimalID);
    }
}

Grundlegender Ablauf

Wie wechselt man von Klassen in OO zu funktionaler Programmierung? Wie andere gesagt haben; Sie können, aber Sie nicht wirklich. Der Sinn des Obenstehenden ist zu demonstrieren, dass Sie nicht einmal Klassen (im herkömmlichen Sinne der Welt) verwenden sollten, wenn Sie Java und C # ausführen. Sobald Sie Code in einer serviceorientierten Architektur (DDD, Layered, Tiered, Hexagonal, was auch immer) schreiben, sind Sie funktional einen Schritt näher, da Sie Ihre Daten (Domänenmodelle) von Ihren logischen Funktionen (Services) trennen.

OO Language ist FP einen Schritt näher gekommen

Sie können sogar noch etwas weiter gehen und Ihre SOA-Services in zwei Typen aufteilen.

Optionale Klasse Typ 1 : Common Interface-Implementing Services für Einstiegspunkte. Dies wären "unreine" Einstiegspunkte, die andere Funktionen "rein" oder "unrein" aufrufen können. Dies können Ihre Einstiegspunkte aus einer RESTful-API sein.

Optionale Klasse Typ 2 : Pure Business Logic Services. Dies sind statische Klassen mit "reiner" Funktionalität. In FP bedeutet "Pure", dass es keine Nebenwirkungen gibt. Es wird nirgendwo explizit der Status oder die Persistenz festgelegt. (Siehe Anmerkung 5)

Wenn Sie also an Klassen in objektorientierten Sprachen denken, die in einer serviceorientierten Architektur verwendet werden, kommt dies nicht nur Ihrem OO-Code zugute, sondern lässt die funktionale Programmierung auch leicht verständlich erscheinen.

Anmerkungen

Hinweis 1 : Das ursprüngliche objektorientierte Design "Rich" oder "Active-Record" ist noch vorhanden. Früher, als die Leute es vor einem Jahrzehnt oder länger "richtig machten", gab es eine Menge Legacy-Code wie diesen. Das letzte Mal, als ich sah, dass diese Art von Code (richtig gemacht) aus einem Videospiel stammt, Codebase in C ++, in dem sie den Speicher präzise kontrollierten und nur über sehr begrenzten Speicherplatz verfügten. Ganz zu schweigen von FP und serviceorientierten Architekturen, die keine Hardware in Betracht ziehen sollten. Sie legen jedoch Wert auf die Fähigkeit, sich ständig zu ändern, gewartet zu werden, variable Datengrößen zu haben und andere Aspekte. In Videospielen und Computer-KI steuern Sie die Signale und Daten sehr genau.

Hinweis 2 : Domänenmodelle weisen weder ein polymorphes Verhalten noch externe Abhängigkeiten auf. Sie sind "isoliert". Das bedeutet nicht, dass sie zu 100% anämisch sein müssen. Sie können eine Menge Logik in Bezug auf ihre Konstruktion und veränderbare Eigenschaftsänderung haben, wenn dies zutrifft. Siehe DDD "Value Objects" und Entities von Eric Evans und Mark Seemann.

Anmerkung 3 : Linq und Lambda sind sehr verbreitet. Wenn ein Benutzer eine neue Funktion erstellt, verwendet er selten Func oder Callable als Parameter, während es in FP seltsam wäre, eine App ohne Funktionen zu sehen, die diesem Muster folgen.

Anmerkung 4 : Polymorphismus nicht mit Vererbung verwechseln. Ein CatModel erbt möglicherweise AnimalBase, um zu bestimmen, welche Eigenschaften ein Tier normalerweise hat. Aber wie ich zeige, sind Modelle wie dieses ein Code-Geruch . Wenn Sie dieses Muster sehen, können Sie es aufschlüsseln und in Daten umwandeln.

Anmerkung 5 : Reine Funktionen können Funktionen als Parameter akzeptieren. Die eingehende Funktion ist möglicherweise unrein, aber möglicherweise rein. Zu Testzwecken wäre es immer rein. Aber in der Produktion kann es, obwohl es als rein behandelt wird, Nebenwirkungen enthalten. Das ändert nichts an der Tatsache, dass die reine Funktion rein ist. Die Parameterfunktion kann jedoch unrein sein. Nicht verwirrend! : D


-2

Sie könnten so etwas tun .. php

    function say($whostosay)
    {
        if($whostosay == 'cat')
        {
             return 'purr';
        }elseif($whostosay == 'dog'){
             return 'bark';
        }else{
             //do something with errors....
        }
     }

     function speak($whostosay)
     {
          return $whostosay .'\'s '.say($whostosay);
     }
     echo speak('cat');
     >>>cat's purr
     echo speak('dog');
     >>>dogs's bark

1
Ich habe keine negativen Stimmen abgegeben. Ich vermute jedoch, dass dieser Ansatz weder funktional noch objektorientiert ist.
Manoj R

1
Das vermittelte Konzept kommt jedoch dem in der funktionalen Programmierung verwendeten Mustervergleich nahe, dh es $whostosaywird zum Objekttyp, der bestimmt, was ausgeführt wird. Das Obige kann geändert werden, um zusätzlich einen anderen Parameter zu akzeptieren, $whattosayso dass ein Typ, der ihn unterstützt (z. B. 'human'), davon Gebrauch machen kann.
syockit
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.