2009-10-22 86 views
20

(撇开你应该让他们在所有的问题。)getter和setter风格

我一直喜欢只使用函数重载给你相同的名称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()); 

当然,我是正确的,但我想知道,如果库作家有什么好理由?

+26

“自然我是对的”这非常有趣,我希望它的目的是作为一个笑话。 – 2009-10-22 21:24:35

回答

30

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

而且,正如其他人所指出的,有些人更喜欢省略“得到”,离开“设置”,即

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

该公约是相当清楚的还有,我不会有任何读到这个问题。

+2

好点。假设使用你的代码的人不只是一个知道你住在哪里的杀人狂,但也有点困惑! – 2009-10-22 21:35:44

1

虽然Ed的评论是真实的,但我确实比setter/getter antipattern更喜欢实际属性。当您的域图中1/3的方法是由eclipse生成的虚拟方法时,就会出现问题。

但是,如果没有第一类属性,我认为反模式最有意义。

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

obj.set (control shift space)的制定者
obj.get (control shift space)的干将

+0

为什么它是一个“反模式”,当第一类属性只是语法糖的同一事物?这个概念是一样的,它只是实现的不同而已。 – 2009-10-22 21:45:10

+0

从某种意义上说,这是一种反模式,它可能是一个班轮。 private property int value; //现在可以与IoC容器一起使用;好极了。 “我在所有函数的顶部重复了30行代码,这是一个反模式,代码的工作原理!” – 2009-10-22 22:02:27

+0

我认为他的意思是让getter/setter完全是反模式 - 这不一定是真实的 - 请参阅我对jmucchiello的评论 – 2009-10-22 22:06:40

5

我一直喜欢省略对我的干将“得到”,因为你这样做,与rate()代替getRate()。但是对于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? 
+0

这是Qt和java风格。 http://qt.gitorious.org/qt/pages/ApiDesignPrinciples ---> goto“命名的艺术” – 2009-10-22 22:59:42

6

如何int rate();void setRate(int value);?这具有不具有相同名称的两个功能做不同事情的优点,并且仍然允许period() * rate()

+1

可能会导致人们寻找getXXX – 2009-10-22 21:33:29

+0

这是Qt和java风格的混淆。 http://qt.gitorious.org/qt/pages/ApiDesignPrinciples ---> goto“命名的艺术” – 2009-10-22 22:57:27

5

几年前,我会完全同意。最近,怀疑开始走上正轨,因为这使得吸气剂或二流剂的地址变得模糊不清。有了像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)); 
); 

撇开你应该让他们在所有;-)

+0

bind()甚至更糟bind2nd()是使我变得事情的事情C++被无法挽回地破坏了。没有人能合理地期望解析,更不用说写了,正确的代码行! – 2009-10-22 22:04:55

+1

好点。重载本身很不错,但是当你想要开始使用函数地址时,它会受到阻碍。 - @mgb:不要低估同胞。也可以使用'std :: mem_fun_ref',但由于重载,类型必须指定:'std :: mem_fun_ref (&A :: Foo)'。 – UncleBens 2009-10-22 22:19:50

4

我会继续前进,何况这应该是一个社区维基问题的问题。

当我开始学习C++我看了风格指南,和谷歌的一些点是好的:

以大写
  • 方法(它只是漂亮)。
  • getter plainly and lowecase(rate)。
  • 明确和小写的设置者(setRate)。
+0

好吧 - 这只是一种闲散的咖啡休息时间。 – 2009-10-22 21:59:16

2

简洁是重要的,但不以不完整或具有误导性为代价。出于这个原因,我更喜欢GetFoo()和SetFoo()到Foo()和Foo(int foo)。

1

就我个人而言,我认为成对发现的获取者和设置者是从“视觉”语言及其“属性”中传出的代码气味。在“良好”类中,数据成员是只写或只读的,但不能读/写。

我认为getter和setter的最常见原因是没有足够深入地携带对象模型。在你的例子中,为什么总数会通过这个周期和费率?他们不是班上的成员吗?所以你只应该设定时间和费率,你只能得到一个总数。

有可能是例外,但我只是讨厌看一个类,并找到“getX/setX,getY/setY等等”似乎没有足够的想法来思考应该如何使用这个类,而是让作者让EASY类获得这些数据,这样他就不必考虑应该如何使用这个类。

当然,我是正确的。

+0

想象一下3d点类型。它将有很多内部函数来完成各种数学工作,但最终需要全部6个get/set x/y/z函数。 – 2009-10-22 22:02:41

+0

@mgb:我个人不相信3d点类型应该首先隐藏成员(除了可能因为您可能想使用数组作为内部表示)。 – UncleBens 2009-10-22 22:16:20

2

有几个层次的“获取”和“设置”

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

所以get/set方法可以归因有用的意义,是这是更大,一致的命名策略的一部分。

0

我强制执行的方法应该总是一个动词,而一个类应该总是一个名词(除了函数,出于显而易见的原因)。在这种情况下,必须使用get/set前缀来保持一致性。这就是说,我完全同意埃德斯旺格。这对我来说总结为使用这些前缀毫不费力。

1

另一个没有人提到的问题是函数重载的情况。拿这个(做作和不完整的)例子:

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到我工作的一个项目的警告集,你看,这显示在所有的地方。

+0

你不会碰巧知道等价于-Woverloaded-virtual for MSVC? – 2009-10-23 03:38:21

+1

@Greg抱歉,我没有。实际上我发现MSVC的警告(从VC8开始)基本上是适得其反的(bool和int之间转换的性能警告,之前被声明为class?)。由于我在两个平台上构建,所以我通常依靠gcc来处理所有的警告需要。 – Tom 2009-10-23 13:26:45

0

我更喜欢避免获取和设置标签,编译器不需要这些信息来完成这些简单属性的大部分工作。

你可以有问题:

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 
+2

您不会为编译器编写有意义的名称,而是为需要使用代码的程序员编写。 – Triskeldeian 2016-08-24 09:00:52

+0

请不要认为写短/聪明/简洁的代码会自动更好。编写代码,以便您和您的同事在6个月后知道发生了什么,而不会把头发拉出来。 – nenchev 2017-03-24 04:51:12

0

如果你消气简直是rate(),你的编译器会抱怨它的其他rate符号的重新定义,只要你给你的领域的良好有意义的名称那样。在这种情况下,你需要做一些愚蠢的事情,比如给你的会员_rate或其他类似的方法。我个人很讨厌看到/输入那些下划线,所以倾向于使用getRate()方法。

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