2009-10-22 130 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()方法。

這顯然是主觀的,這恰好是我個人的偏好。