In OOP empfiehlt es sich, mit Schnittstellen zu kommunizieren, nicht mit Implementierungen. Also schreiben Sie beispielsweise so etwas (von Seq
ich meine scala.collection.immutable.Seq
:)):
nicht etwa wie folgt:
%Vor%In reinen funktionalen Programmiersprachen wie Haskell haben Sie jedoch keinen Subtyp-Polymorphismus und stattdessen Ad-hoc-Polymorphismus über Typklassen. So haben Sie zum Beispiel den Listdatentyp und eine monadische Instanz für die Liste. Sie müssen sich keine Gedanken über die Verwendung einer Schnittstelle / abstrakten Klasse machen, weil Sie kein solches Konzept haben.
In hybriden Sprachen, wie Scala, haben Sie beide Klassen (durch ein Muster, tatsächlich, und nicht erstklassige Bürger wie in Haskell, aber ich schweife ab) und Subtyp Polymorphismus. In scalaz
, cats
und so weiter haben Sie natürlich monadische Instanzen für konkrete Typen, nicht für die abstrakten.
Endlich die Frage: Angesichts dieses Hybridismus von Scala respektierst du immer noch die OOP-Regel, um mit Interfaces zu sprechen oder einfach mit konkreten Typen zu sprechen, um Funktoren, Monaden usw. direkt zu nutzen zu einem konkreten Typ konvertieren, wann immer Sie sie brauchen? Anders gesagt, ist es in Scala immer noch eine gute Übung, mit Interfaces zu sprechen, auch wenn Sie FP statt OOP nutzen wollen? Wenn nicht, was wäre, wenn Sie sich für List
entschieden hätten und später festgestellt hätten, dass eine Vector
die bessere Wahl gewesen wäre?
P.S .: In meinen Beispielen habe ich eine einfache Methode verwendet, aber das gleiche gilt für benutzerdefinierte Typen. Zum Beispiel:
%Vor%Was ich hier angreifen würde, ist Ihr Konzept "concrete vs. interface". Sieh es dir so an: Jeder Typ hat eine Schnittstelle, im allgemeinen Sinn des Begriffs "Schnittstelle". Ein "konkreter" Typ ist nur ein begrenzender Fall.
Sehen wir uns Haskell-Listen aus diesem Blickwinkel an. Was ist die Schnittstelle einer Liste? Nun, Listen sind ein algebraischer Datentyp , und alle diese Datentypen haben die gleiche allgemeine Form von Schnittstelle und Vertrag:
Wenn Sie es mit diesen Begriffen betrachten, denke ich, dass die folgende Regel in beiden Paradigmen ziemlich gut funktioniert:
Sie fragen also nicht mehr, ob ein Typ "konkret" oder "abstrakt" ist - egal, ob er Ihren Anforderungen entspricht.
Das sind meine zwei Cent zu diesem Thema. In Haskell haben Sie Datentypen (ADTs). Sie haben sowohl Listen (verknüpfte Listen) als auch Vektoren (int-indizierte Arrays), aber sie haben keinen gemeinsamen Supertyp. Wenn Ihre Funktion eine Liste annimmt, können Sie ihr keinen Vektor übergeben.
Da es sich bei Scala um eine hybride OOP-FP-Sprache handelt, haben Sie auch einen Subtyp-Polymorphismus, so dass es Ihnen nicht egal ist, ob der Clientcode List
oder Vector
übergibt, sondern nur Seq
(möglicherweise unveränderlich). und du bist fertig.
Ich denke, um auf diese Frage zu antworten, müssen Sie sich eine andere Frage stellen: "Will ich FP in toto umarmen?". Wenn die Antwort ja lautet, sollten Sie nicht Seq
oder eine andere abstrakte Oberklasse im Sinne von OOP verwenden. Die Ausnahme von dieser Regel ist natürlich die Verwendung eines Merkmals / einer abstrakten Klasse beim Definieren von ADTs in Scala. Beispielsweise:
In diesem Fall würde man natürlich Tree[A]
als einen Typ benötigen und dann z. B. Mustervergleich verwenden, um zu bestimmen, ob es entweder Empty
oder Node[A]
ist.
Ich denke, mein Gefühl für dieses Thema wird durch das rote Buch () bestätigt Funktionale Programmierung in Scala ). Dort verwenden sie nie Seq
, aber List
, Vector
und so weiter. Auch haskellers interessieren sich nicht für diese Probleme und verwenden Listen, wann immer sie Linked-List-Semantik und -Vektoren benötigen, wann immer sie Int-Indexed-Array-Semantik benötigen.
Wenn Sie andererseits OOP verwenden und Scala als besseres Java verwenden möchten, dann sollten Sie der OOP-Best Practice folgen, um talk mit Interfaces zu kommunizieren nicht zu Implementierungen.
Wenn Sie denken: "Ich würde mich eher für hauptsächlich funktional entscheiden, dann sollten Sie Erik Meijers Der Fluch der ausgeschlossenen Mitte .
Tags und Links scala functional-programming oop scalaz scala-cats