Delphi32 schreef op 13 augustus 2002 @ 00:38:
[...]
Ben benieuwd wat
code:
1
2
3
| SELECT COUNT(*) FROM GoTForum
WHERE user = 'Alarmnummer'
AND replytext LIKE '*multimethods/multidispatch*' |
zou opleveren
Ik zie je die termen zo vaak gebruiken, kun je eens uitleggen wat je ermee bedoelt? Ik kan me er (nog) geen voorstelling van maken.
Als je een methode m hebt bij een object a en die heeft argumenten b en c.
code:
1
2
3
| class A{
void m(B b, C c){}
} |
Dan zou je hier ook een functie van mogen maken alhoewel dat vanuit oo perspectief vreemd overkomt:
void m(A a, B b, C c){}
Dit is exact hetzelfde alleen een andere manier van schrijven. (Denk hier even goed over na, dit is erg belangrijk).
Stel nu dat A abstract is
code:
1
2
3
| abstract class A{
abstract void m(B b, C c);
} |
en je hebt de volgende 2 kinderen:
code:
1
2
3
4
5
6
7
| class A1 extends A{
void public m(B b, C c){System.out.println("A1");}
}
class A2 extends A{
void public m(B b, C c)(System.out.println("A2");)
} |
Dan heb je dus 2 methode implementaties:
void m(A1 a, B b, C c){System.out.println("A1");}
void m(A2 a, B b, C c){System.out.println("A2");}
Stel nu dat ik functie m ga aanroepen:
m(new A1(),new B(),new C())
Dan krijg je op je scherm te zien 'A1' omdat de juiste methode wordt gekozen op basis van het 1e argument. De selectie van de methode implementatie vind dus plaats op het 1e argument, en daarom heet dat ook wel single dispatch. Bij een multidispatch methode kan dit over meerdere argumenten plaats vinden, en dat zal ik hieronder even uitlegen.
Stel dat B ook 2 subclasses heeft, B1 en B2 en B is verder abstract. Dan zou ik bij A1 en A2 het volgende kunnen doen:
code:
1
2
3
4
5
6
7
8
9
| class A1 extends A{
void public m(B1 b, C c){System.out.println("A1,B1");}
void public m(B2 b, C c){System.out.println("A1,B2");}
}
class A2 extends A{
void public m(B1 b, C c)(System.out.println("A2,B1");)
void public m(B2 b, C c)(System.out.println("A2,B2");)
} |
En ik roep het nu als volgt aan:
m(new A1(),new B2(),new C());
Dan krijg je op je scherm te zien 'A1,B2', omdat je nu de juiste methode hebt gekozen op basis van 2 argumenten (double dispatch).
In het functionele programmeren is het vrij gebruikelijk om op deze manier te werken. Hieronder laat ik een stukje pseudo code zien hoe je types zou kunnen checken in een functionele prog taal:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| boolean isSubTypeOf(subType Type, superType Type);
isSubTypeOf(IntType subType ,IntType superType) = true; //een int is een subtype van int
isSubTypeOf(Type subType ,IntType superType) = false; //ieder ander type is geen subtype van een int
isSubTypeOf(RealType subType ,RealType superType) = true;//real is subtype van real
isSubTypeOf(IntType subType ,RealType superType) = true; //int is subtype van real
isSubTypeOf(Type subType ,Type superType)= false;
//ieder ander type van een real (afgezien van int en real dus) is geen subtype.
... |
Wat je je hier ziet is dus pattern matching en dat is een uitermate krachtig middel in functionele programmeertalen. Mbv multidispatch heb je dus ook een redelijke versie van pattern matching tot je beschikking. En zoals je ziet heb je dus nu voor alles classes deze functie gedefinieerd in 1 keer en daarom is het ook veel overzichtelijker dan dat je hem over je hele class hierarchie gaat verspreiden. In nice kan je dit allemaal doen met multimethodes. Dit bied je de mogelijkheid om methodes te definieeren buiten objecten, maar je kan ze wel normaal aanroepen: intType.isSubTypeOf(realType), dus je houdt je oo notatie.
Over het algemeen wordt een double dispatch gesimuleerd mbv het visitor design pattern, en zie mijn signature hoe ik daar over denk

Maar als je vanuit de taal zelf multi dispatch ondersteuning hebt, dan kan je gewoon veel mooiere code schrijven. En verder kan je met het visitor design pattern er voor zorgen dat je in 1 'class' alles afhandelende methodes hebt mbt een bepaald stuk functionaliteit en dat is dus ook iets wat je met een multimethod kan oplossen.
Ik hoop dat je er iets van hebt begrepen