简体   繁体   English

吸气剂和二传手风格

[英]getters and setters style

(Leaving aside the question of should you have them at all.) (暂不回答你应该拥有它们的问题。)

I have always preferred to just use function overloading to give you the same name for both getter and setters. 我一直希望只使用函数重载为getter和setter提供相同的名称。

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() );

Naturally I am correct, but i wondered if the library writers had any good reason ? 当然我是对的,但我想知道图书馆作家是否有任何理由?

I would prefer the get/set versions because it is more clear as to what is going on. 我更喜欢get / set版本,因为它更清楚了解发生了什么。 If I saw rate() and rate(10), how do I know that rate(10) isn't simply using 10 in the calculation to return the rate? 如果我看到rate()和rate(10),我怎么知道rate(10)不是简单地在计算中使用10来返回率? I don't, so now I have to start searching to figure out what is going on. 我没有,所以现在我必须开始寻找弄清楚发生了什么。 A single function name should do one thing, not two opposing things. 单个函数名称应该做一件事,而不是两个相反的事情。

Also, as others have pointed out, some prefer to omit the 'get' and leave the 'set', ie, 另外,正如其他人所指出的那样,有些人更喜欢省略'get'并离开'set',即

int Rate( );
void SetRate( int value );

That convention is pretty clear as well, I wouldn't have any problem reading that. 这个惯例也很清楚,我读这个也不会有任何问题。

I have always preferred to omit the 'get' on my getters, as you do, with rate() instead of getRate() . 我总是倾向于使用rate()而不是getRate()来省略getter上的'get'。 But overloading for the setter does not seem like a very good idea to me, since the name rate doesn't convey that the object is being mutated. 但是对于我而言,重载对于我来说似乎不是一个好主意,因为名称rate并没有表明对象正在变异。 Consider: 考虑:

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?

How about int rate(); int rate();怎么样int rate(); and void setRate(int value); void setRate(int value); ? This has the virtue of not having two functions of the same name doing different things, and still allows period() * rate() . 这样做的好处是不会有两个同名的函数做不同的事情,并且仍然允许使用period() * rate()

A few years ago, I would have agreed completely. 几年前,我完全同意了。 More recently, a doubt began to make its way, because that makes taking the address of a getter or setter ambiguous. 最近,一个疑问开始成为现实,因为这使得吸气剂或制定者的地址变得模棱两可。 With tools like tr1::bind, this is really annoying. 使用像tr1 :: bind这样的工具,这真的很烦人。

For example: 例如:

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));
);

Leaving aside the question of should you have them at all ;-) 撇开你应该拥有它们的问题;-)

I'll go ahead and mention this should be a community wiki question. 我会继续提及这应该是一个社区维基问题。

When I started learning C++ I looked for style guides, and Google's was good for some points: 当我开始学习C ++时,我寻找样式指南,谷歌对某些方面有好处:

  • Methods in uppercase (it's just prettier). 大写的方法(它更漂亮)。
  • getters plainly and lowecase ( rate ). 明显和低级( rate )。
  • setters explicitly and lowercase ( setRate ). setter显式和小写( setRate )。

Being concise is important, but not at the cost of being incomplete or misleading. 简洁是很重要的,但不能以不完整或误导为代价。 For that reason, I prefer GetFoo() and SetFoo() to Foo() and Foo(int foo). 出于这个原因,我更喜欢GetFoo()和SetFoo()到Foo()和Foo(int foo)。

There are several levels to "Getting" and "Setting" “获取”和“设置”有几个级别

  • I use Get and Set for "fast" operations. 我使用Get和Set进行“快速”操作。
  • If something will take a longer time to execute, then it will often be a Calc, as these names imply that some work has to be done to retrieve the result. 如果某些事情需要花费更长的时间来执行,那么它通常会是一个Calc,因为这些名称意味着必须完成一些工作来检索结果。
  • For longer operations, you start to get into prefixes like Load/Save, Query/Store, Read/Write, Search/Find etc. 对于更长的操作,您开始进入加载/保存,查询/存储,读/写,搜索/查找等前缀。

So Get/Set can be ascribed a useful meaning, and be part of a larger, consistent naming strategy. 因此,Get / Set可以归结为有用的含义,并且是更大,一致的命名策略的一部分。

Another issue no one else has mentioned is the case of function overloading. 没有人提到的另一个问题是函数重载的情况。 Take this (contrived and incomplete) example: 拿这个(人为的和不完整的)例子:

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
};

Without that using clause, users of Contractor cannot query the salary because of the overload. 如果没有using子句, Contractor用户就不会因为过载而查询薪水。 I recently added -Woverloaded-virtual to the warning set of a project I work on, and lo and behold, this showed up all over the place. 我最近将-Woverloaded-virtual添加到我正在处理的项目的警告集中,并且看,这显示在所有地方。

While Ed's comment is true, I do prefer actual properties over the setter/getter antipattern. 虽然Ed的评论是真的,但我确实更喜欢实际属性而不是setter / getter反模式。 When 1/3rd of the methods in your domain graph are dummy methods that have been generated by eclipse, there's something wrong. 当域图中1/3的方法是由eclipse生成的伪方法时,就会出现问题。

Without first class properties, however, I believe the antipattern makes the most sense. 但是,如果没有一流的属性,我相信反模式最有意义。

Furthermore, it makes code completion easier. 此外,它使代码完成更容易。

obj.set (control shift space) for setters obj.set (control shift space)
obj.get (control shift space) for getters obj.get (control shift space)

Personally, I think getters and setters found in pairs are a code smell carried over from "visual" languages and their "properties". 就个人而言,我认为成对发现的吸气剂和制定者是“视觉”语言及其“属性”带来的代码味道。 In a "good" class, the data members are writeonly or readonly but not read/write. 在“好”类中,数据成员是writeonly或readonly但不是读/写。

I think the most common cause of getters and setters is not carrying the object model deep enough. 我认为getter和setter最常见的原因是没有足够深入地携带对象模型。 In your example, why is total being passed the period and the rate? 在你的例子中,为什么总计通过了期间和费率? Aren't they members of the class? 他们不是班上的成员吗? So you should only be setting the period and the rate and you should only be getting a total. 所以你应该只设定期限和费率,你应该只得到一个总数。

There are probably exceptions but I just hate looking at a class and finding "getX/setX, getY/setY, etc. etc." 可能有异常,但我只是讨厌看一个类并找到“getX / setX,getY / setY等等”。 It just seems there wasn't enough thought put into how the class SHOULD be used and rather the author made the class EASY to get at the data so he wouldn't have to consider how the class should be used. 似乎没有足够的思考如何使用类,而是作者让类EASY得到数据,所以他不必考虑如何使用类。

Naturally I am correct. 我当然是对的。

I enforce the convention in which a method should always be a verb and a class should always be a noun (except for functors, for obvious reasons). 我强制执行一种方法,其中一个方法应该始终是一个动词,一个类应该始终是一个名词(出于显而易见的原因除了仿函数)。 In which case, a get/set prefix must be used for consistency. 在这种情况下,必须使用get / set前缀来保持一致性。 That said, I also agree entirely with Ed Swangren. 也就是说,我也完全赞同Ed Swangren。 This sums to me as using those prefixes a no-brainer. 这总结给我使用这些前缀是一个明智的选择。

I prefer to avoid the get and set labels, the information is not needed for the compiler to do it's job for most of these simple properties. 我更喜欢避免使用get和set标签,编译器不需要这些信息来完成大多数这些简单属性的工作。

you can have issues: 你可以有问题:

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

If your getter is simply rate() , your compiler would complain that its a redefinition of your other rate symbol, provided you gave your field a good meaningful name like that. 如果你的getter只是rate() ,你的编译器会抱怨它重新定义了你的其他rate符号,只要你给你的字段一个很好的有意义的名字就好了。 In that case you need to do something silly like name your member _rate or some other similar approach. 在这种情况下,你需要做一些愚蠢的事情,如命名你的成员_rate或其他类似的方法。 I personally hate seeing/typing those underscores, so tend to go with the getRate() approach. 我个人讨厌看/键入那些下划线,所以倾向于采用getRate()方法。

This is obviously subjective and this just happens to be my personal preference. 这显然是主观的,这恰好是我个人的偏好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM