Es ist sehr spät, aber ich stimme bis zu einem gewissen Grad mit dem überein, was oxbow_lakes sagte. Ich habe vor kurzem von Python zu Scala übergegangen, und zu wissen, wie Java funktioniert - insbesondere Java Einschränkungen in Bezug auf generische Typen - hat mir geholfen, bestimmte Aspekte von Scala zu verstehen.
Am auffälligsten:
-
Java hat eine schreckliche Fehlfunktion, die als "type erasure" bekannt ist. Diese Unzulänglichkeit ist leider auch in der JVM vorhanden. Dies betrifft insbesondere die Programmierung mit generischen Typen - ein Problem, das in dynamisch typisierten Sprachen wie Ruby und Python überhaupt nicht auftritt, in statisch typisierten Sprachen aber sehr groß ist. Scala kann dieses Problem so gut wie möglich umgehen, aber das Ausmaß des Bruchs bedeutet, dass einiges davon unweigerlich in Scala durchschlägt. Darüber hinaus sind einige der Korrekturen in Scala für dieses Problem (z.B. Manifeste) neu und hakelig, und erfordern wirklich ein Verständnis dessen, was darunter passiert. Beachten Sie, dass dieses Problem Ihr Verständnis von Scala anfangs wahrscheinlich nicht beeinträchtigen wird, aber Sie werden damit konfrontiert werden, wenn Sie anfangen, echte Programme zu schreiben, die generische Typen verwenden, da es Dinge gibt, die Sie versuchen werden zu tun, die einfach nicht funktionieren, und Sie werden nicht wissen, warum, bis Sie die Beschränkungen verstehen, die durch die Typenlöschung erzwungen werden.
-
Früher oder später werden Sie auch auf Probleme stoßen, die mit einem anderen Fehler von Java zusammenhängen, nämlich der Aufteilung der Typen in Objekte (Klassen) und primitive Typen (ints, floats, booleans) - und insbesondere der Tatsache, dass primitive Typen nicht Teil des Objektsystems sind. Scala versteckt dies sehr gut vor Ihnen, aber es kann hilfreich sein, zu wissen, was Java in bestimmten Eckfällen tut, die ansonsten schwierig sein könnten -- insbesondere wenn es um generische Typen geht, vor allem wegen der in #1 beschriebenen Unzulänglichkeit der Typenlöschung. (Typ-Löschung führt auch zu einem großen Leistungseinbruch bei der Verwendung von Arrays, Hash-Tabellen und ähnlichen generischen Typen anstelle von Primitiven; dies ist ein Bereich, in dem Java-Kenntnisse sehr hilfreich sind.)
-
Fehlfunktion Nr. 3: Arrays werden auch in Java speziell und nicht orthogonal behandelt. Scala versteckt dies nicht ganz so nahtlos wie bei den Primitiven, aber viel besser als bei der Typ-Löschung. Der Versteckmechanismus wird manchmal offengelegt (z.B. der ArrayWrapper-Typ), was gelegentlich zu Problemen führen kann -- aber das größte Problem in der Praxis ist, nicht überraschend, wieder mit generischen Typen.
-
Scala-Klassenparameter und die Art und Weise, wie Scala mit Klassenkonstruktoren umgeht. In diesem Fall ist Java nicht kaputt. Scala wohl auch nicht, aber die Art und Weise, wie es mit Klassenkonstruktoren umgeht, ist eher ungewöhnlich, und in der Praxis hatte ich Schwierigkeiten, sie zu verstehen. Ich war nur in der Lage, das Verhalten von Scala zu verstehen, indem ich herausfand, wie der relevante Scala-Code in Java (oder besser gesagt, in kompiliertes Java) übersetzt wird, und dann überlegte, was Java tun würde. Da ich davon ausgehe, dass Ruby in dieser Hinsicht ähnlich wie Java funktioniert, glaube ich nicht, dass Sie auf allzu viele Probleme stoßen werden, auch wenn Sie vielleicht die gleiche mentale Umwandlung vornehmen müssen.
-
E/A. Dies ist eher ein Problem der Bibliothek als ein Problem der Sprache. In den meisten Fällen bietet Scala seine eigenen Bibliotheken, aber Scala hat nicht wirklich eine E/A-Bibliothek, so dass Sie so ziemlich keine andere Wahl haben, als die E/A-Bibliothek von Java direkt zu verwenden. Für einen Python- oder Ruby-Programmierer ist diese Umstellung etwas schmerzhaft, da Javas E/A-Bibliothek groß und sperrig ist und für einfache Aufgaben, wie z. B. das Iterieren über alle Zeilen einer Datei, nicht sonderlich einfach zu verwenden ist.
Beachten Sie, dass Sie neben E/A auch Java-Bibliotheken direkt für andere Fälle verwenden müssen, in denen Sie mit dem Betriebssystem oder verwandten Aufgaben interagieren, z. B. bei der Arbeit mit Zeiten und Daten oder beim Abrufen von Umgebungsvariablen, aber das ist normalerweise nicht allzu schwer herauszufinden. Die anderen wichtigen Java-Bibliotheken, die Sie möglicherweise verwenden müssen, sind
- Aufruf von Unterprozessen, auch etwas groß und sperrig
- Networking - aber das ist immer etwas mühsam
- Reflexion, d.h. die dynamische Untersuchung der Methoden und/oder Felder einer Klasse oder der dynamische Aufruf einer Methode nach Namen, wenn der Name zur Kompilierzeit nicht bekannt ist. Dies ist etwas esoterisches Zeug, mit dem die meisten Leute nichts zu tun haben müssen. Anscheinend wird Scala 2.10 eine eigene Reflection-Bibliothek haben, aber derzeit muss man die Java-Reflection-APIs verwenden, was bedeutet, dass man eine ganze Menge darüber wissen muss, wie Scala nach Java konvertiert wird. (Glücklicherweise gibt es eine -print-Option für den Scala-Compiler, die genau zeigt, wie diese Konvertierung erfolgt).