Was ist der Vorteil der Verwendung einer abstrakten Klasse anstelle eines Merkmals (abgesehen von der Leistung)? Es scheint, dass abstrakte Klassen in den meisten Fällen durch Merkmale ersetzt werden können.
371
Ich kann mir zwei Unterschiede vorstellen
Es gibt einen Abschnitt in der Programmierung in Scala mit dem Titel "Zu Merkmalen oder nicht zu Merkmalen?" welches diese Frage anspricht. Da die 1. Ausgabe online verfügbar ist, hoffe ich, dass es in Ordnung ist, das Ganze hier zu zitieren. (Jeder ernsthafte Scala-Programmierer sollte das Buch kaufen):
Wie @Mushtaq Ahmed erwähnte, können für ein Merkmal keine Parameter an den primären Konstruktor einer Klasse übergeben werden.
Ein weiterer Unterschied ist die Behandlung von
super
.Weitere Informationen finden Sie im Rest von Kapitel 12 .
Edit 1 (2013):
Es gibt einen subtilen Unterschied im Verhalten abstrakter Klassen im Vergleich zu Merkmalen. Eine der Linearisierungsregeln besteht darin, dass die Vererbungshierarchie der Klassen beibehalten wird, wodurch abstrakte Klassen später in der Kette verschoben werden, während Merkmale problemlos eingemischt werden können. Unter bestimmten Umständen ist es tatsächlich vorzuziehen, sich an der letzten Position der Klassenlinearisierung zu befinden Daher könnten abstrakte Klassen dafür verwendet werden. Siehe Einschränken der Klassenlinearisierung (Mixin-Reihenfolge) in Scala .
Edit 2 (2018):
Ab Scala 2.12 hat sich das binäre Kompatibilitätsverhalten von Merkmalen geändert. Vor 2.12 mussten zum Hinzufügen oder Entfernen eines Mitglieds zum Merkmal alle Klassen neu kompiliert werden, die das Merkmal erben, auch wenn sich die Klassen nicht geändert haben. Dies liegt an der Art und Weise, wie Merkmale in JVM codiert wurden.
Ab Scala 2.12 werden Merkmale in Java-Schnittstellen kompiliert , sodass sich die Anforderungen etwas entspannt haben. Wenn das Merkmal eine der folgenden Aktionen ausführt, müssen seine Unterklassen immer noch neu kompiliert werden:
Wenn dies nicht der Fall ist, können Sie es jetzt aktualisieren, ohne die Binärkompatibilität zu beeinträchtigen.
quelle
If outside clients will only call into the behavior, instead of inheriting from it, then using a trait is fine
- Könnte jemand erklären, was hier der Unterschied ist?extends
vswith
?extends
undwith
. Es ist rein syntaktisch. Wenn Sie von mehreren Vorlagen erben, wird die ersteextend
, alle anderen erhaltenwith
, das war's. Stellen Sie sichwith
ein Komma vor :class Foo extends Bar, Baz, Qux
.Für alles, was es wert ist, empfiehlt Odersky et al. In der Programmierung in Scala , dass Sie im Zweifelsfall Merkmale verwenden. Sie können sie später bei Bedarf jederzeit in abstrakte Klassen ändern.
quelle
Abgesehen von der Tatsache, dass Sie nicht mehrere abstrakte Klassen direkt erweitern können, sondern mehrere Merkmale zu einer Klasse mischen können, ist es erwähnenswert, dass Merkmale stapelbar sind, da Superaufrufe in einem Merkmal dynamisch gebunden sind (es bezieht sich auf eine Klasse oder ein Merkmal, das zuvor gemischt wurde der Momentane).
Aus Thomas 'Antwort im Unterschied zwischen abstrakter Klasse und Merkmal :
quelle
Wenn Sie eine abstrakte Klasse erweitern, zeigt dies, dass die Unterklasse von ähnlicher Art ist. Dies ist meiner Meinung nach bei der Verwendung von Merkmalen nicht unbedingt der Fall.
quelle
In Programming Scala sagen die Autoren, dass abstrakte Klassen eine klassische objektorientierte "is-a" -Beziehung eingehen, während Merkmale eine Scala-Art der Komposition sind.
quelle
Abstrakte Klassen können Verhalten enthalten - Sie können mit Konstruktorargumenten parametrisiert werden (welche Merkmale nicht können) und eine Arbeitseinheit darstellen. Merkmale repräsentieren stattdessen nur ein einzelnes Merkmal, eine Schnittstelle einer Funktionalität.
quelle
trait Enumerable
mit vielen Hilfsfunktionen definieren , würde ich sie nicht als Verhalten bezeichnen, sondern nur als Funktionen, die mit einer Funktion verbunden sind.quelle