题
(撇开的问题你应该有他们所有的.)
我总是优选的只是使用功能超载来给你同样的名称为吸气,并制定者。
int rate() { return _rate; }
void rate(int value) { _rate = value; }
// instead of
int getRate() { return _rate; }
void setRate(int value) { _rate = value; }
// mainly because it allows me to write the much cleaner
total( period() * rate() );
// instead of
setTotal( getPeriod() * getRate() );
当然我是正确的,但我想知道如果库作了任何好的理由吗?
解决方案
我更喜欢get / set版本,因为它更清楚发生了什么。如果我看到rate()和rate(10),我怎么知道rate(10)不是简单地在计算中使用10来返回率?我没有,所以现在我必须开始寻找弄清楚发生了什么。单个函数名称应该做一件事,而不是两个相反的事情。
另外,正如其他人所指出的那样,有些人宁愿省略'get'并留下'set',即
int Rate( );
void SetRate( int value );
这个惯例也很清楚,我读这个也不会有任何问题。
其他提示
我总是倾向于使用 rate()
而不是 getRate()
来省略getter上的'get'。但是对于我来说,重载器对于我来说似乎不是一个好主意,因为名称 rate
并不表示该对象正在变异。考虑:
total(period() * rate()); // awesome, very clear
rate(20); // Looks like it computes a rate, using '20'...but for what? And why ignore the return value?
int rate();
和 void setRate(int value);
怎么样?这样做的好处是不会有两个同名的函数做不同的事情,并且仍然允许 period()* rate()
。
几年前,我完全同意了。最近,一个疑问开始成为现实,因为这使得吸气剂或制定者的地址变得模棱两可。使用像tr1 :: bind这样的工具,这真的很烦人。
例如:
struct A
{
void Foo(int);
int Foo()const;
};
std::vector<A> v = ....;
std::vector<int> foos;
// Extract Foo
std::transform(
v.begin(), v.end(),
std::back_inserter(foos),
//Ambiguous
// std::tr1::bind(&A::Foo)
//must write this instead. Yuck!
std::tr1::bind(static_cast<int(Foo::*)()>(&A::Foo));
);
撇开你应该拥有它们的问题; - )
我将继续前进,并说这应该是一个社会wiki的问题。
当我开始学习C++我看着风格的指南,和谷歌的是良好的一些要点:
- 方法以大写形式(它只是漂亮).
- 吸气清楚和lowecase(
rate
). - 制定者的明确和小写(
setRate
).
简洁很重要,但不能以不完整或误导为代价。出于这个原因,我更喜欢GetFoo()和SetFoo()到Foo()和Foo(int foo)。
有几个层次以"得到"和"设定"
- 我的使用获取和设置"快速"行动。
- 如果事情将需要更长的时间来执行,然后它会往往是一个计算,因为这些名称意味着一些工作有待完成检索的结果。
- 对于较长的运作,开始进入前缀就像装载/保存、查询/储存、读写、搜索和查找等等。
所以Get/Set可以归因于一个有用的意义,并以更大部分的一部分,一致命名的战略。
虽然Ed的评论是真的,但我确实更喜欢setter / getter反模式的实际属性。域图中1/3的方法是由eclipse生成的虚拟方法时,就会出现问题。
但是,如果没有第一类属性,我相信反模式最有意义。
此外,它使代码完成更容易。
obj.set(控制班次空间)
for setters
getter的 obj.get(控制班次空间)
就我个人而言,我认为成对发现的吸气剂和固定剂是从“视觉”中带来的代码气味。语言及其“属性”。在“好”中class,数据成员是writeonly或readonly但不是读/写。
我认为getter和setter的最常见原因是没有足够深入地携带对象模型。在你的例子中,为什么总计通过了期间和费率?他们不是班上的成员吗?所以你应该只设定期限和费率,你应该只得到一个总数。
可能存在异常,但我只是讨厌查看课程并找到“getX / setX,getY / setY等”等。看起来似乎没有足够的思考如何使用类,而是作者让类EASY得到数据,所以他不必考虑如何使用类。
当然我是对的。
没有其他人提到的另一个问题是函数重载的情况。拿这个(人为的和不完整的)例子:
class Employee {
virtual int salary() { return salary_; }
virtual void salary(int newSalary) { salary_ = newSalary; }
};
class Contractor : public Employee {
virtual void salary(int newSalary) {
validateSalaryCap(newSalary);
Employee::salary(newSalary);
}
using Employee::salary; // Most developers will forget this
};
如果没有 using
子句, Contractor
的用户由于超载而无法查询薪水。我最近将 -Woverloaded-virtual
添加到我正在处理的项目的警告集中,并且看,它出现在所有地方。
我强制执行一种约定,其中一个方法应该始终是一个动词,一个类应该总是一个名词(出于显而易见的原因除了仿函数)。在这种情况下,必须使用get / set前缀来保持一致性。也就是说,我也完全赞同Ed Swangren。这总结给我使用这些前缀是一个明智的选择。
我更喜欢避免使用get和set标签,编译器不需要这些信息来完成大多数这些简单属性的工作。
你可能有问题:
class Stuff {
void widget( int something ); // 'special' setter
const Widget& widget( int somethingelse ) const; // getter
}
Stuff a;
a.widget(1); // compiler won't know which widget you mean, not enough info
如果你的getter只是 rate()
,你的编译器会抱怨它重新定义了你的其他 rate
符号,只要你给你的字段一个很有意义的名字就好了那。在这种情况下,你需要做一些愚蠢的事情,比如命名你的成员 _rate
或其他一些类似的方法。我个人不喜欢看/键入那些下划线,所以倾向于使用 getRate()
方法。
这显然是主观的,这恰好是我个人的偏好。