Vielleicht fehlt mir etwas, aber ich würde gerne wissen, ob es einen guten Grund gibt, warum dieser Code kompiliert werden sollte
role L {
method do-l (Int, Int --> Int ) { ... }
}
class A does L {
method do-l (Int $a, Real $b --> Str) {
.Str ~ ": Did you expect Int?" with $a + $b
}
}
my $a = A.new;
say $a.do-l: 2, 3.323
Dies wird ausgegeben
5.323: Did you expect Int?
Ich war neugierig, ob jemand einen Weg kennt, wie der Compiler zumindest eine Warnung mit der implementierten Signatur der Rolle auslösen kann L
.
L.do-l
hat eine Methode, die nicht übereinstimmt, und in jedem Fall hat die Klassenmethode Vorrang, daher sollte auf beiden BasenA
sdo-l
aufgerufen werden. Das Hinzufügen von aInt
und aReal
wird a seinReal
....
(obwohl dies im Produktionscode sinnvoll ist, kann dies zu Verwirrung führen)role foo {}.new
der automatisch in so etwas umgewandelt wirdanon class foo does role foo {}.new
), ist so transparent, dass die Leute möglicherweise nicht erkennen, dass es sich um ein Wortspiel handelt, daher mein vorheriger Kommentar. Es ist schön, dass dieses Wortspiel im Alleingang die primäre Alternative zur Vererbung und zur Delegierung ermöglicht, nämlich das Organisieren und Konstruieren von Typen mithilfe von Kompositionen , aber imo ist es wichtig, dass die Leute nicht ganz aus den Augen verlieren, dass.new
es sich um ein Wortspiel handelt.Antworten:
Sie erhalten dies, wenn Sie der Methodendeklaration Folgendes voranstellen
multi
:Damit zeigt Ihr Programm:
Ich denke, die Absicht des Designs war es, zwei Begriffe der polymorphen Zusammensetzung zu unterstützen:
Ohne das
multi
bezieht sich die Durchsetzung nur auf das Vorhandensein einer Methode mit dem richtigen Namen ; Parameter werden ignoriert.Mit dem
multi
deckt die Durchsetzung auch den Namen und alle Parameter ( oder einige ) ab.Meine persönliche Meinung, ob es einen guten Grund gibt für:
Unterstützung von zwei Varianten des Methodenpolymorphismus? Manchmal ist es hilfreich, die strikte Einhaltung der Signatur durchzusetzen. Manchmal stört es.
Unterscheiden sie über
multi
? Für die vollständige Durchsetzung der Signatur muss die Implementierung von Klassen / Rollen über eine Methode mit genau derselben Signatur verfügen . Was aber, wenn eine implementierende Klasse / Rolle einenint
anstelleInt
eines Parameters verarbeiten möchte ? Raku geht Kompromisse ein. Vorausgesetzt, eine implementierende Klasse / Rolle verfügt über eine genau kompatible Methode, kann sie auch Variationen aufweisen. Der perfekte Weg, dies zu vermitteln, besteht darin, einer Stub-Methode das Präfix zu gebenmulti
.Haben Sie die Standardeinstellung nur Polymorphismus? Wir hätten die
multi
Semantik als Standard wählen können und Benutzer einonly
Präfix schreiben lassen, wenn sie nur Polymorphismus nennen wollten. Dies würde jedoch die übliche Situation umkehren (dh Stub-Methoden ignorieren). Im Allgemeinen besteht die Absicht darin, dass Raku eine breite Palette von Einschränkungen für seine Funktionen bietet, von entspannt bis angespannt, und eine Standardeinstellung für eine bestimmte Funktion auswählt, die auf der Grundlage des Feedbacks der Benutzer im Laufe der Jahre als richtig beurteilt wird.Was ist, wenn die Standardeinstellung nicht richtig erscheint? Was ist, wenn das vorhandene Spektrum an Strikturen nicht ausreicht? Was ist, wenn eine Gruppe denkt, wir sollten nach links gehen und eine andere denkt, wir sollten nach rechts gehen?
Raku verfügt über (imo) bemerkenswerte Governance-Mechanismen zur Unterstützung der benutzergesteuerten Sprachentwicklung. Auf der obersten Ebene gibt es Elemente wie die Geflechtarchitektur . Auf der untersten Ebene gibt es Elemente wie versionierbare Typen . In der Mitte befinden sich Elemente
RoleToClassApplier
, die den Prozess des Anwendens einer Rolle auf eine Klasse vermitteln. Dies ist der Punkt, an dem eine erforderliche Methode gefunden werden muss oder die Konstruktion der Klasse fehlschlägt. Kurz gesagt, wenn die Sprache nicht wie gewünscht funktioniert, einschließlich Strikturen, können Sie sie zumindest im Prinzip so ändern, dass sie funktioniert.quelle
multi
diesen Stummel einsetzen zu müssen, ist nicht intuitiv, aber jetzt macht es dank Ihrer Erklärung tatsächlich Sinn.Ich gehe davon aus, dass Sie hier fragen, warum es keine Warnung in Bezug auf das Stubbing gibt. Normalerweise muss eine Stubbed-Methode implementiert werden - aber das war's.
Sie können hier in Rakudos Quelle sehen, wie die Rollen zu Klassen zusammengesetzt sind (im
$yada
Grunde bedeutet das$is-stubbed
):Sie können also sehen, dass die Logik nur darin besteht, zu prüfen, ob eine Methode mit demselben Namen vorhanden ist. Es ist definitiv möglich, ein Modul zu schreiben, das diese Logik aktualisiert, indem die Methode apply () erweitert oder die
RoleToClassApplier
Klasse vollständig ersetzt wird . Es könnte jedoch schwierig sein. Betrachten Sie zum Beispiel:Sollten wir die Stubbed-Methode als korrekt implementiert betrachten? Aber jemand anderes könnte später sagen
class C is Letter
und plötzlich ist es nicht implementiert. (Natürlich könnten wir sagen, dass die beste Logik zumindest den identischen oder Supertyp erfordert, aber das ist restriktiver als für dynamische Sprachen erforderlich, IMO).AFAICT gibt es keine Methode, die während der Komposition für Rollen aufgerufen wird und die auch auf die Klasse verweist (tatsächlich wird überhaupt keine Methode aufgerufen
add_method
). Daher gibt es keine Möglichkeit, einen eigenen Scheck innerhalb der Rolle zu schreiben. (aber ich könnte mich irren, vielleicht könnten Raiph, Lizmat oder Jnthn mich korrigieren).Meine Empfehlung in diesem Fall wäre, anstatt es zu stubben, einfach eine Würfelanweisung hinzuzufügen:
Dies erfasst es nicht bei der Kompilierung, aber wenn zu irgendeinem Zeitpunkt eine andere Methode
L
aufgerufen werdendo-l(Int, Int)
muss - selbst wenn die komponierende Klasse andere Signaturen implementiert -, wird es aufgerufen und der Fehler wird ziemlich schnell abgefangen.quelle