getter 和 setter 风格

发布于 2024-08-08 20:20:24 字数 462 浏览 6 评论 0原文

(抛开是否应该拥有它们的问题。)

我一直更喜欢使用函数重载来为 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() );

当然我是对的,但我想知道图书馆作者是否有任何充分的理由?

(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.

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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

倾`听者〃 2024-08-15 20:20:24

我更喜欢 get/set 版本,因为它更清楚发生了什么。如果我看到rate()和rate(10),我怎么知道rate(10)不是简单地在计算中使用10来返回汇率?我不知道,所以现在我必须开始寻找到底发生了什么。单个函数名应该做一件事,而不是做两件相反的事情。

另外,正如其他人指出的那样,有些人更喜欢省略“get”并保留“set”,即,

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

该约定也很清楚,我阅读它不会有任何问题。

I would prefer the get/set versions because it is more clear as to what is going on. 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? 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', i.e.,

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

That convention is pretty clear as well, I wouldn't have any problem reading that.

风情万种。 2024-08-15 20:20:24

我总是喜欢像您一样,使用 rate() 而不是 getRate() 来省略 getter 上的“get”。但对我来说,setter 的重载似乎不是一个好主意,因为名称 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?

I have always preferred to omit the 'get' on my getters, as you do, with rate() instead of getRate(). 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. 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?
歌入人心 2024-08-15 20:20:24

int rates();void setRate(int value); 怎么样?这样做的优点是不会让两个同名的函数做不同的事情,并且仍然允许period() * rates()

How about int rate(); and 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().

只有影子陪我不离不弃 2024-08-15 20:20:24

几年前,我会完全同意。最近,一个疑问开始出现,因为这使得获取 getter 或 setter 的地址变得不明确。对于像 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));
);

抛开“你是否应该拥有它们”的问题;-)

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.

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

如歌彻婉言 2024-08-15 20:20:24

我会继续提到这应该是一个社区维基问题。

当我开始学习 C++ 时,我寻找风格指南,Google 的在某些方面很不错:

  • 大写的方法(它只是更漂亮)。
  • getter 简单且小写 (rate)。
  • 设置器显式且小写 (setRate)。

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:

  • Methods in uppercase (it's just prettier).
  • getters plainly and lowecase (rate).
  • setters explicitly and lowercase (setRate).
撩心不撩汉 2024-08-15 20:20:24

简洁很重要,但不能以不完整或误导为代价。因此,我更喜欢 GetFoo() 和 SetFoo() 而不是 Foo() 和 Foo(int foo)。

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

╭⌒浅淡时光〆 2024-08-15 20:20:24

“获取”和“设置”有几个级别,

  • 我使用 Get 和 Set 进行“快速”操作。
  • 如果某件事需要更长的时间来执行,那么它通常是一个 Calc,因为这些名称意味着必须完成一些工作才能检索结果。
  • 对于较长的操作,您开始使用诸如加载/保存、查询/存储、读/写、搜索/查找等前缀。

因此,获取/设置可以被赋予有用的含义,并成为更大、一致的命名策略的一部分。

There are several levels to "Getting" and "Setting"

  • I use Get and Set for "fast" operations.
  • 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.
  • 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.

寄意 2024-08-15 20:20:24

另一个没有人提到的问题是函数重载的情况。以这个(人为的且不完整的)示例为例:

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 添加到我从事的一个项目的警告集中,你瞧,这到处都出现了。

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. 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.

林空鹿饮溪 2024-08-15 20:20:24

虽然 Ed 的评论是正确的,但我确实更喜欢实际属性而不是 setter/getter 反模式。当域图中 1/3 的方法是 eclipse 生成的虚拟方法时,就会出现问题。

然而,如果没有一流的属性,我相信反模式是最有意义的。

此外,它使代码完成变得更容易。

obj.set(控制移位空间) 用于设置器
用于吸气剂的 obj.get(控制移位空间)

While Ed's comment is true, I do prefer actual properties over the setter/getter antipattern. When 1/3rd of the methods in your domain graph are dummy methods that have been generated by eclipse, there's something wrong.

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.get (control shift space) for getters

无畏 2024-08-15 20:20:24

就我个人而言,我认为成对出现的 getter 和 setter 是从“视觉”语言及其“属性”中遗留下来的代码味道。在“好”类中,数据成员是只写或只读的,但不是读/写的。

我认为 getter 和 setter 的最常见原因是对象模型没有足够深入。在您的示例中,为什么总计超过了期间和比率?他们不是班级成员吗?因此,您应该只设置期限和费率,并且您应该只获得总计。

可能有例外,但我只是讨厌查看一个类并找到“getX/setX、getY/setY 等”。似乎没有足够的考虑应该如何使用该类,而是作者使该类易于获取数据,因此他不必考虑应该如何使用该类。

我自然是对的。

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.

I think the most common cause of getters and setters is not carrying the object model deep enough. 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." 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.

Naturally I am correct.

不羁少年 2024-08-15 20:20:24

我强制执行这样的约定:方法应始终是动词,类应始终是名词(出于显而易见的原因,函子除外)。在这种情况下,必须使用 get/set 前缀来保持一致性。也就是说,我也完全同意埃德·斯旺格伦的观点。对我来说,使用这些前缀是理所当然的。

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. That said, I also agree entirely with Ed Swangren. This sums to me as using those prefixes a no-brainer.

牵你的手,一向走下去 2024-08-15 20:20:24

我更喜欢避免使用 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

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.

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
血之狂魔 2024-08-15 20:20:24

如果你的 getter 只是 rate(),你的编译器会抱怨它是对你的其他 rate 符号的重新定义,只要你给你的字段一个像这样有意义的名称。在这种情况下,您需要做一些愚蠢的事情,例如为您的会员命名 _rate 或其他类似的方法。我个人讨厌看到/键入这些下划线,因此倾向于使用 getRate() 方法。

这显然是主观的,这恰好是我个人的偏好。

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. In that case you need to do something silly like name your member _rate or some other similar approach. I personally hate seeing/typing those underscores, so tend to go with the getRate() approach.

This is obviously subjective and this just happens to be my personal preference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文