#include <iostream>
int main()
{
std::cout << "Привет, я Борислав!\n";
return 0;
}
DynaMix: A New Take on Polymorphism
DynaMix: A New Take on Polymorphism
DynaMix: A New Take on Polymorphism
DynaMix: A New Take on Polymorphism
using Drawable = Library_Magic(void, draw, (ostream&));
struct Square {
void draw(ostream& out) const { out << "Square\n"; }
};
struct Circle {
void draw(ostream& out) const { out < "Circle\n"; }
};
void f(const Drawable& d) {
d.draw(cout);
}
int main() {
f(Square{});
f(Circle{});
}
collide(obj1, obj2);
DynaMix: A New Take on Polymorphism
DynaMix: A New Take on Polymorphism
Two more mobile games in development
Compose and modify polymorphic objects at run time
module FlyingCreature
def move_to(target)
puts can_move_to?(target) ?
"flying to #{target}"
: "can't fly to #{target}"
end
def can_move_to?(target)
true # flying creatures don't care
end
end
module AfraidOfEvens
def can_move_to?(target)
target % 2 != 0
end
end
a = Object.new
a.extend(FlyingCreature)
a.move_to(10) # -> flying to 10
a.extend(AfraidOfEvens)
a.move_to(10) # -> can’t fly to 10
DynaMix means "Dynamic Mixins"
struct cd_reader {
string get_sound() const {
return cd.empty() ? "silence" : ("cd: " + cd);
}
string cd;
};
template <typename Self>
struct headphones {
const Self* self() const {
return static_cast<const Self*>(this);
}
void play() {
cout << "Playing " << self()->get_sound()
<< " through headphones\n";
}
};
struct diskman : public cd_reader, public headphones<diskman> {};
struct boombox : public cd_reader, public speakers<boombox> {};
struct ipod : public mp3_reader, public headphones<ipod> {};
template <typename Player>
void use_player(Player& player) {
player.play();
}
int main() {
diskman dm;
dm.cd = "Led Zeppelin IV (1971)";
use_player(dm); // -> Playing "Led Zeppelin IV (1971)"
ipod ip;
ip.mp3 = "Led Zeppelin - Black Dog.mp3";
use_player(ip); // -> Playing "Led Zeppelin - Black Dog.mp3"
}
dynamix::object
– just an empty object
dynamix::object sound_player; // just an empty dynamix::object
dynamix::mutate(sound_player)
.add<cd_reader>()
.add<headphones_output>();
sound_player.get<cd_reader>()->insert("Led Zeppelin IV (1971)");
// play is a message
play(sound_player); // cant have sound_player.play() :(
// -> Playing CD "Led Zeppelin IV (1971)" through headphones
dynamix::mutate(sound_player)
.remove<headphones_output>()
.add<speakers_output>();
play(sound_player);
// -> Playing CD "Led Zeppelin IV (1971)" THROUGH SPEAKERS
Messages:
// Declare
DYNAMIX_MESSAGE_0(string, get_sound);
DYNAMIX_MESSAGE_1(void, play);
DYNAMIX_MESSAGE_2(int, foo, float, arg1, string, arg2);
// Define
DYNAMIX_DEFINE_MESSAGE(get_sound);
DYNAMIX_DEFINE_MESSAGE(play);
DYNAMIX_DEFINE_MESSAGE(foo);
We fully separate the interface from the implementation.
Message vs Method
Late binding and Smalltalk
struct Foo {
void bar();
};
Foo foo;
foo.bar(); // message
void Foo::bar() {} // method
Mixins:
DYNAMIX_DECLARE_MIXIN(cd_reader);
DYNAMIX_DECLARE_MIXIN(headphones_output);
// That’s all we need to mutate
class cd_reader {
public:
string get_sound() {
return cd.empty() ? "silence" : ("CD " + cd);
}
void insert(const string& cd) {
_cd = cd;
}
string _cd;
};
DYNAMIX_DEFINE_MIXIN(cd_reader, get_sound_msg);
// ...
DYNAMIX_DEFINE_MIXIN(mp3_reader, get_sound_msg);
class headphones_output {
public:
void play() {
cout << "Playing " << get_sound(dm_this)
<< " through headphones\n";
}
};
DYNAMIX_DEFINE_MIXIN(headphones_output, play_msg);
dm_this
is like self
: the owning objectMixQuest
std::function
Borislav Stanimirov / ibob.github.io / @stanimirovb
DynaMix is here: github.com/ibob/dynamix/
Link to these slides: http://ibob.github.io/slides/dynamixv2/
Slides license Creative Commons By 3.0