我正在写一个非常大的图书馆,我发现自己一直在编写几乎相同的访问者。我已经有了几十个访问器,如下面的那个。
问题:如何声明/实现访问器以保存键入所有这些重复代码? (请不要#defines;我正在寻找C ++结构。)
更新:是的,我做需要访问器函数,因为我需要指向这些访问器以获取名为Property Descriptors的东西,这可以大大节省我的GUI代码(非库)。
private:
bool _visible;
public:
bool GetVisible() const { return _visible; }
void SetVisible (bool value);
// Repeat for Get/SetFlashing, Get/SetColor, Get/SetLineWidth, etc.
void Element::SetVisible (bool value)
{
_visible = value;
this->InvalidateSelf(); // Call method in base class
// ...
// A bit more code here, identical in 90% of my setters.
// ...
}
// Repeat for Get/SetFlashing, Get/SetColor, Get/SetLineWidth, etc.
答案 0 :(得分:33)
我发现自己一直在编写几乎相同的访问者。我已经有了几十个访问器,如下面的那个。
这是一种确定的设计气味,你正在编写存取器"为了它"。你真的需要它们吗?你真的需要一个低水平的公众"得到"和"设置"每个人的手术?这不太可能。
毕竟,如果您正在为每个私有数据成员编写一个getter和setter,并且每个私有数据成员具有相同的逻辑,那么您也可以公开数据成员。
相反,您的类应该具有有意义的和语义操作,这些操作在其职责过程中可能会或可能不会使用私有数据成员。您会发现每个有意义的操作都与其他操作完全不同,因此重复代码的问题就会被解决。
早上好表示:
简单:避免访问者。编写你的课程来做某事,而不是做点什么。
即使对于那些对他们没有任何帮助的操作,例如控制可见性,您应该有bool isVisible() const
,void show()
和void hide()
。你会发现,当你开始这样的编码时,它会促使人们远离模板,而不是为了它#34;吸气剂和setter方法。
答案 1 :(得分:26)
虽然我认为Lightness Races in Orbit是一个非常好的观点,但也有一些方法可用于实现"重复代码",可以应用,假设我们确实有一个类有许多相似的东西需要单独控制,所以继续这样,说我们有几个这样的方法:
void Element::Show()
{
visible = true;
Invalidate();
// More code goes here.
}
void Element::Hide()
{
visible = false;
Invalidate();
// More code goes here.
}
现在,在我看来,这打破了DRY(不要重复自己)的原则,所以我们应该这样做:
void Element::UpdateProperty(bool &property, bool newValue)
{
property = value;
Invalidate();
// More code goes here.
}
现在,我们可以通过这样做来实现Show
和Hide
,Flash
,Unflash
,Shaded
等,避免在每个功能中重复。
void Element::Show()
{
UpdateProperty(visible, true);
}
如果类型不是bool,例如有一个position
,我们可以这样做:
template<typename T>void Element::UpdateProperty(T &property, T newValue)
{
property = value;
Invalidate();
// More code goes here.
}
并且MoveTo
变为:
void Element::MoveTo(Point p)
{
UpdateProperty(position, p);
}
编辑根据以前未公开的信息添加到问题:
显然,上述技术同样适用于执行此类工作的任何形式的功能:
void Element::SetVisible(bool value)
{
UpdateProperty(visible, value);
}
将与上述Show
一样有效。它并不意味着您可以放弃声明函数,但它减少了对函数内部代码的需求。
答案 2 :(得分:7)
我同意Lightness。你应该为手头的任务设计你的课程,如果你需要这么多的getter和setter,你可能会做错事。
也就是说,大多数好的IDE都允许你生成简单的getter和setter,有些甚至可以让你自定义它们。您可以将重复代码保存为模板,并在需要时选择代码片段。
您还可以使用emacs和Vim(使用Ultisnips)等可自定义的编辑器,并创建一些自定义帮助功能,以使您的工作轻松。自动化的任务已经成熟。
答案 3 :(得分:0)
你应该用任何语言编写get / set函数集的唯一时间是它是否只是读取或写入一个简单变量;如果你所做的一切都让人们更难阅读,那么就不要费心包办对数据的访问。如果这就是您正在做的事情,请停止做任何事情。
如果您确实需要一组get / set函数,请不要调用它们来获取和设置 - 使用赋值和类型转换(并巧妙地执行)。这样,您可以使代码更具可读性,而不是更少。
这非常不优雅:
class get_set {
int value;
public:
int get() { return value; }
void set(int v) { value = v; }
};
这好一点
class get_set_2 {
value_type value;
bool needs_updating;
public:
operator value_type const & () {
if (needs_updating) update(); // details to be found elsewhere
return value;
}
get_set_2& operator = (value_type t) {
update(t); // details to be found elsewhere
return *this;
}
};
如果您没有采用第二种模式,请不要做任何事情。