getters and setters style

2019-02-07 20:44发布

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

13条回答
Luminary・发光体
2楼-- · 2019-02-07 20:59

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?
查看更多
爷的心禁止访问
3楼-- · 2019-02-07 21:00

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.

查看更多
在下西门庆
4楼-- · 2019-02-07 21:01

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.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-02-07 21:05

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

查看更多
Deceive 欺骗
6楼-- · 2019-02-07 21:05

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.

查看更多
聊天终结者
7楼-- · 2019-02-07 21:10

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.

查看更多
登录 后发表回答