polymorphism |
---|
ad hoc polymorphism |
parametric polymorphism |
subtyping |
multiple dispatch (tsz. multiple dispatches)
this
) vagy második, hanem akár mindegyik argumentum típusa alapján.
Olyan mechanizmus, ahol a hívott függvény implementációja az összes paraméter futásidejű típusától függ.
Ez túlmutat a single dispatch (pl. C++-beli virtual
metódusok) és double dispatch technikán is.
Képzeld el, hogy egy add(a, b)
műveletet akarsz végrehajtani, és a működése attól függ, hogy a
és b
milyen típusúak:
add(int, int)
→ egész számok összeadásaadd(int, string)
→ sztringgé alakít és összefűzadd(Foo, Bar)
→ valamilyen egyedi logikaA multiple dispatch lényege, hogy ezek közül a megfelelő változat automatikusan kiválasztásra kerül futásidőben a tényleges típusok szerint.
C++ csak single dispatch-t támogat natívan (virtuális függvényeken keresztül). De double dispatch-t kézzel implementálhatsz (mint korábban láttuk), míg multiple dispatch-hez trükkökre vagy külső könyvtárakra van szükség.
Nyelv | Támogatás |
---|---|
Julia | ✅ Natív multiple dispatch |
Clojure | ✅ Multimethods |
Common Lisp | ✅ Generic functions |
Python | 🚫 nem natív, de functools.singledispatch és multipledispatch csomaggal lehet
|
C++ | 🚫 nincs beépítve, de kézzel megvalósítható Visitorral vagy map-el |
from multipledispatch import dispatch
@dispatch(int, int)
def add(a, b):
return a + b
@dispatch(str, str)
def add(a, b):
return a + b
@dispatch(int, str)
def add(a, b):
return str(a) + b
print(add(1, 2)) # 3
print(add("a", "b")) # ab
print(add(3, "x")) # 3x
Több lehetőség van:
Kézzel implementálod minden párosítást (kombinatorikusan bonyolult).
Példa:
#include <iostream>
#include <typeinfo>
using namespace std;
class Expr;
class IntExpr;
class AddExpr;
class Expr {
public:
virtual void accept(Expr& other) = 0;
virtual ~Expr() = default;
};
class IntExpr : public Expr {
public:
void accept(Expr& other) override {
// multiple dispatch-szerű logika
if (typeid(other) == typeid(IntExpr))
cout << "Int + Int" << endl;
else if (typeid(other) == typeid(AddExpr))
cout << "Int + AddExpr" << endl;
}
};
class AddExpr : public Expr {
public:
void accept(Expr& other) override {
if (typeid(other) == typeid(IntExpr))
cout << "AddExpr + Int" << endl;
else if (typeid(other) == typeid(AddExpr))
cout << "AddExpr + AddExpr" << endl;
}
};
Ez nem ideális: lassú (typeid
), merev, nem típusbiztos.
Fogalom | Leírás |
---|---|
Single dispatch | A függvény a hívó objektum típusától függ (pl. C++) |
Double dispatch | A függvény két objektum típusától függ |
Multiple dispatch | A függvény több (akár összes) argumentum típusától függ |