Folgender Code implementiert Mehrfachdispatch in JavaScript (ECMAScript 5, um genau zu sein). Ich habe ihn unter die MIT-Lizenz gestellt, und er kann als mulkiple-dispatch.js heruntergeladen werden.
Implementierung
"use strict";
function MulkipleDispatchObject(prototype, slots) {
var inheritsFrom = function(object, other) {
return (object !== null
&& (object === other
|| inheritsFrom(Object.getPrototypeOf(object), other)));
};
var realSlots = {};
for (var slot in slots) {
if (!(slots[slot] instanceof Array)) {
realSlots[slot] = slots[slot];
} else {
(function(slot) {
var mulkiSlot = { method: true, value: function() {
for (var alternative in slots[slot]) {
var applies = true;
alternative = slots[slot][alternative];
var typelist = alternative['dispatch'];
for (var i = 0; i in typelist && i in arguments; i++) {
if (!(arguments[i] === null
|| arguments[i] instanceof typelist[i]
|| inheritsFrom(arguments[i], typelist[i]))) {
applies = false;
break;
}
}
if (applies) {
return alternative['value'].apply(this, arguments);
}
}
return Object.getPrototypeOf(this)[slot].apply(this, arguments);
}};
realSlots[slot] = mulkiSlot;
})(slot);
}
}
return Object.create(prototype, realSlots);
}
MulkipleDispatchObject.create = MulkipleDispatchObject;
Beispiel
Verwendet wird der Code zum Beispiel wie folgt (hier mit dem printf-Modul von Narwhal):
var printf = require('printf');
// ----- Konstruktoren -----
function Being(name) {
return MulkipleDispatchObject.create(Being.prototype, {
name: { value: name, enumerable: true },
toString: { method: true, value: function() {
return printf.sprintf("%s", this.name);
}},
greet: [{ dispatch: [], value: function(other) {
printf.printf("%s grüßt %s.", this, other);
}}]
});
}
function Person(name) {
return MulkipleDispatchObject.create(Person.prototype, {
name: { value: name, enumerable: true },
greet: [
{ dispatch: [Person], value: function(other) {
printf.printf("%s sagt: \"Mulk, %s\".", this, other.name);
}},
{ dispatch: [Cat], value: function(other) {
printf.printf("%s streichelt %s.", this, other);
}}]
});
}
Person.prototype = Being(null, null);
Person.prototype.constructor = Person;
function Cat(name, owner) {
return MulkipleDispatchObject.create(Cat.prototype, {
name: { value: name, enumerable: true },
owner: { value: owner, enumerable: true, modifiable: true },
greet: [{ dispatch: [], value: function(other) {
printf.printf("%s miaut %s an.", this, other);
}}]
});
}
Cat.prototype = Being(null, null);
Cat.prototype.constructor = Cat;
// ----- Hauptprogramm -----
var matthias = Person("Matthias");
var simon = Person("Simon");
var magdalena = Person("Magdalena");
var mauzi = Cat("Mauzi", magdalena);
matthias.greet(magdalena); // => Matthias sagt: "Mulk, Magdalena".
magdalena.greet(matthias); // => Magdalena sagt: "Mulk, Matthias".
simon.greet(matthias); // => Simon sagt: "Mulk, Matthias".
matthias.greet(simon); // => Matthias sagt: "Mulk, Simon".
mauzi.greet(matthias); // => Mauzi miaut Matthias an.
matthias.greet(mauzi); // => Matthias streichelt Mauzi.
Anmerkungen
Die Implementierung ist sehr naiv, und entsprechend unterwältigend wird vermutlich die Performance sein. Es gibt momentan außerdem keine Möglichkeit, nachträglich Mehrfachmethoden hinzuzufügen.
Comments
Submit a comment
Note: This website uses a JavaScript-based spam prevention system. Please enable JavaScript in your browser to post comments. Comment format is plain text. Use blank lines to separate paragraphs.