Вызов функции «function» стал своего рода контекстно-зависимым.Полагаю, этот прием можно использовать для поддержки предметно-ориентированного программирования .
Субъектно-ориентированное программирование основано на наблюдении, что свойства объекта не присущи самому объекту, а зависят от того, кто воспринимает этот объект.Например, с точки зрения человека дерево - это не еда, а с точки зрения термитов дерево - это еда.Объектно-ориентированная парадигма не поддерживает это наблюдение напрямую, и люди часто приходят к сложным неестественным проектам, потому что они пытаются объединить все различные субъективные представления объекта в один объект («класс»), следуя бездумно руководящим принципам ООП.
Итак, давайте попробуем явным образом сформулировать субъективное восприятие, используя рассматриваемый прием для получения чувствительности к контексту.
template<class FoodSource>
class FoodFrom {};
//forward declarations
class Tree;
class Termite;
class Human;
//property "food" of a tree
template<>
class FoodFrom<Tree>
{
public:
FoodFrom(Tree& _tree): tree(_tree) {}
//termite perception of tree as food
operator FoodFor<Termite>()
{
int happiness_increase = 5;
tree.mass -= 10;
return FoodFor<Termite>(happiness_increase);
}
//human perception of tree as food
operator FoodFor<Human>()
{
int happiness_increase = 0;
return FoodFor<Human>(happiness_increase);
}
private:
Tree& tree;
};
//property "food" of a termite
template<>
class FoodFrom<Termite>
{
public:
FoodFrom(Termite& _termite): termite(_termite) {}
//human perception of termite as food
operator FoodFor<Human>()
{
int happiness_increase = -100;
//apparently, the termite ought to be terminated due to such a violent act
termite.~Termite();
return FoodFor<Human>(happiness_increase);
}
private:
Termite& termite;
};
//simple class FoodFor, just for demonstration purposes
class FoodBase
{
public:
FoodBase(int _value) : value(_value) {}
int value;
};
template<class T>
class FoodFor: public FoodBase
{
public:
FoodFor(): FoodBase(0) {}
FoodFor(int _value) : FoodBase(_value) {}
};
class AliveBeing
{
public:
AliveBeing(): happiness(100) {}
bool is_happy()
{
return happiness > 0;
}
void eat()
{
happiness += getMeal()->value;
}
private:
int happiness;
virtual FoodBase* getMeal() = 0;
};
class Tree: public AliveBeing
{
public:
FoodFrom<Tree> getFood(); //see definition below
float mass;
//...
private:
//we don't call getMeal for a tree in this demo
virtual FoodBase* getMeal() { return NULL; }
};
class Termite: public AliveBeing
{
public:
FoodFrom<Termite> getFood(); //see definition below
FoodFor<Termite> meal;
private:
virtual FoodBase* getMeal() { return &meal; }
};
class Human: public AliveBeing
{
public:
FoodFor<Human> meal;
private:
virtual FoodBase* getMeal() { return &meal; }
};
//return proxy "FoodFrom" to "overload" return type
FoodFrom<Tree> Tree::getFood()
{ return FoodFrom<Tree>(*this); }
FoodFrom<Termite> Termite::getFood()
{ return FoodFrom<Termite>(*this); }
//usage
Tree tree;
Termite funny_bug;
//funny_bug gets its perceived value of eating tree
funny_bug.meal = tree.getFood();
funny_bug.eat();
if(funny_bug.is_happy())
funny_bug.goFindThirdPlace();
//...
Human joel;
//joel get its perceived value of eating tree
joel.meal = tree.getFood();
joel.eat();
//...
if(joel.see(funny_bug))
{
joel.meal = funny_bug.getFood();
joel.eat();
}
if(joel.is_happy())
joel.writeAnotherGreatArticle();
Обратите внимание, что дерево не знает, что его ест.
(действительно, великий вопрос заставил меня задуматься над этим)