我仍然有一个小问题,抓住纯OOD的概念.
假设我们有一类人类,我们生活在一个人类行走的世界里(大脑命令腿部),有时树木会消失(人类注意到这一点),有时候人类会随机相互撞击.
前两种情况真的很简单:
class Tree {
private:
void disappear()
{
// call onTreeDisappeared() for all human observers
}
};
class Human {
public:
// The human notices that a tree disappeared
void onTreeDisappeared();
private:
int x, y, z;
// Human wants to walk forward
void moveForward();
// Hit another human, possibly causing him to fall down
void hit(Human &target);
};
Run Code Online (Sandbox Code Playgroud)
现在我遇到了一个非常糟糕的问题.当然,你可以这么说很好
anna.hit(bob);
Run Code Online (Sandbox Code Playgroud)
直到这里我觉得它很好(如果有什么不好就请抱怨)并且读起来像散文(好的OOP代码应该).但是你如何将击球转移到OOP?如果安娜击中鲍勃并且鲍勃跌倒,那么跌倒既不是由安娜也不是鲍勃造成的.它是由命中,失去平衡和物理造成的.
我知道这种情况只有2个选项,但不知怎的,我觉得两个都很糟糕:
public: void fallDown()
{ z = 0; }
public: void hit(Human &target)
{
bool targetFallsDown = true; // could be random or any algorithm you like
if(targetFallsDown)
{ target.fallDown(); }
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,安娜"倒下"鲍勃.但这完全没有任何意义.这并不像安娜抓住鲍勃的身体并将其移向地面.但还有另一种选择:
private: void fallDown()
{ z = 0; }
public: void onHitCausesMeToFallDown()
{ fallDown(); }
public: void hit(Human &target)
{
bool targetFallsDown = true; // could be random or any algorithm you like
if(targetFallsDown)
{ target.onHitCausesMeToFallDown(); }
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,鲍勃的身体"注意到"击中使他跌倒在地,然后他"移动自己"到地面.我认为这比第一种选择更好,但这仍然不知何故感觉不对.
所以,请智能OOP人员向我解释,在现实世界中如何处理案例A修改B的状态但在OOP世界中只有B应该修改B的状态.
CB *_*ley 10
我认为你正陷入试图在课堂上塑造"真实"世界的陷阱而没有你的设计目的.
你的计划应该做什么?一旦你完成了这项工作,那么你就可以开始设计你想要建模的现实世界的哪些方面,以及现实世界的哪些部分无关紧要,不需要建模.将类映射到具体的真实世界对象类型只是因为它易于可视化通常是一个错误.您只需要为您的程序建立重要的概念.
OOD是关于使用抽象和多态等技术来允许对象彼此交互而不必了解彼此的实现.
在您的实现中,您需要确定要建模的行为以及每个对象想要的知识.例如,你可能希望一个人根据他被击中的难度来判断他是否想要跌倒.
void Human::receiveHit(Hit hit)
{
if (hit.IsBigForThisWeight(this->weight))
this->fallDown();
}
Run Code Online (Sandbox Code Playgroud)
请注意,击中我的东西不需要知道或关心它对我有什么影响.这是我对热门的反应.我还建模了一个"命中"对象,因为它对我的程序有意义.任何东西都可以通过创建一个Hit对象并让我接收它来打击我.将来我可能会被公共汽车或火车撞到,而我的班级没有任何变化.