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.