在我最近编写的代码中,我被迫直接访问一个对象的成员来调用它的函数,但是,这样做感觉不对,因为它似乎违反了封装和Demeter法则。然而,我能想出的唯一好的选择是在类中为我可能想要调用的那个成员的每个函数编写我自己的函数,这将是非常乏味和冗余的。例如:
class Object
{
public:
void setNum(int x)
{
num = x;
}
private:
int num;
};
class Object2
{
public:
Object obj;
};
int main()
{
Object2 obj2;
obj2.obj.setNum(5);
}
VS
class Object
{
public:
void setNum(int x)
{
num = x;
}
private:
int num;
};
class Object2
{
public:
void setNum(int x)
{
obj.setNum(x);
}
private:
Object obj;
};
int main()
{
Object2 obj2;
obj2.setNum(5);
}
setNum
中对Object2
的来电被转发到Object
中的同一个功能。这样的设计被认为是不好的做法吗?是否更好地访问obj
?
我也可以从Object2
继承Object
,但在这种情况下,我将继承的类不是设计为基类,而是将受保护的成员公开给Object2
,并且似乎不适合开始,因为它不是一种关系,而且组合将是首选。
我的具体情况:我正在使用SFML制作游戏,有一个类Ship
当然需要一个精灵来代表它在世界上。任何时候我想设置或获得船舶的位置,旋转等。我必须直接访问其精灵或在Ship
中写入冗余转发功能。问题是,做这些事情中的任何一个看起来像代码气味:要么违反封装和Demeter法则,要么写冗余代码。
这里最佳做法是什么?我是否过于挑剔编写简单的转发功能?或者在这种情况下直接访问Ship
的精灵真的没有错吗?
这个问题:C++ Forward method calls to embed object without inheritance实际上正是我所要求的,然而,这两个答案都没有给出一个好的解决方案。一个没有被宽恕,显然有很差的封装,另一个只是使用一个似乎是安慰剂的吸气剂,如果有的话,没有人解决我的主要问题,这是什么是最优雅和可接受的解决方案?
答案 0 :(得分:2)
最好的解决方案在很大程度上取决于封装的基本语义。您需要尽可能地解耦代码。我将在例子中描述:
在这种情况下,没有使用继承,因为继承意味着孩子是其祖先的变体。你可以说BattleShip是一艘船的变种。但是Ship并不是Sprite的变种,它们太不同了,意味着不同的东西。
所以:如果封装类太具体而且不应该在外部可见,或者必须与主对象一致地操作,那么编写一堆代理方法是一个很好的解决方案。否则这些方法只会膨胀你的代码,最好提供一种获取嵌套对象的方法。但在这种情况下,我投票选择了getter方法而不是公共财产。
答案 1 :(得分:1)
尽管经典的 javanese oop学校可以思考,但永远不会忘记DRY(不要重复自己)也被认为是一种很好的做法。
虽然OOP只是C ++可以支持的众多编程范例之一,但是DRY是所有编程的精髓所在,因为第一个汇编程序得到了宏,并且在oop发明者甚至远离他们自己的父母之前很久就是这样。 39;思想和愿望。
对于我的不公平体验的所有内容......如果尊重良好的oop练习迫使你写出重复代码的无用锅炉板,那就意味着
要解决您的具体问题,委托(这种模式通常如何命名)在以下情况下有意义:
在您的情况下,您有一个函数调用可从固定成员访问的固定方法。
这仅针对此特定样本或在您的实现中是否总是这样设计?
如果是这样,如果不仅仅将a.b.m()
缩减为a.m()
,则委托不会添加任何语义值。如果你写的不仅仅是......让我们说 3"什么都不做只是前进"功能你在浪费你的时间。
如果b有50个方法而且你将它设为私有,只委托其中的5个方法,那么它就非常有意义了。