2009-10-22 2 views
20

(Оставляя в стороне вопрос о том, вы должны иметь их вообще.)методы получения и установки типа

Я всегда предпочитал, чтобы просто использовать функцию перегрузки, чтобы дать вам такое же имя, как для добытчика и сеттеров.

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

«Естественно, я прав» Это довольно забавно, я надеюсь, что это было предназначено как шутка. –

ответ

30

Я бы предпочел получить/установить версии, потому что более ясно, что происходит. Если я видел rate() и rate (10), откуда я знаю, что скорость (10) не просто использует 10 в вычислении для возврата ставки? Я этого не делаю, поэтому теперь я должен начать поиск, чтобы выяснить, что происходит. Одно имя функции должно делать одно, а не две противоположные вещи.

Кроме того, как уже отмечалось, некоторые предпочитают опустить «получить» и оставить «набор», т.е.

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

Это условность довольно ясно, как хорошо, я бы не имеет какого-либо проблема считывание эта.

+2

Хорошая точка. Предположите, что человек, использующий ваш код, не просто убийственный маньяк, который знает, где вы живете, но также немного смущен! –

1

Несмотря на то, что комментарий Эд является истинным, я предпочитаю фактические свойства по сравнению с фильтром setter/getter. Когда 1/3 из методов на вашем графе домена являются фиктивными методами, которые были созданы eclipse, есть что-то неправильно.

Без свойств первого класса, однако, я считаю, что антипаттерн имеет наибольший смысл.

Кроме того, упрощает выполнение кода.

obj.set (control shift space) для наладчиков
obj.get (control shift space) для добытчиков

+0

Почему это «антипаттерн», когда свойства первого класса - это просто синтаксический сахар для одного и того же? концепция такая же, это просто реализация, которая отличается. –

+0

Это антипаттерн в том смысле, что это может быть один лайнер. частная собственность int value; // теперь работает с контейнерами IoC; Ура. «Я повторяю 30 строк кода в верхней части всех моих функций. Как это антипаттерн? Код работает!» –

+0

Я думаю, что он имеет в виду наличие геттеров/сеттеров вообще - это анти-шаблон, что не обязательно верно - см. Мой комментарий к jmucchiello –

5

Я всегда предпочитал опускать «получить» на моих добытчиках, как вы, с rate() вместо getRate(). Но перегрузка для сеттера не кажется мне очень хорошей идеей, поскольку имя 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 «искусство именования» –

6

Как насчет int rate(); и void setRate(int value);? Это имеет то преимущество, что не имеет двух функций с тем же именем, что делает разные вещи, и до сих пор позволяет period() * rate().

+1

Возможно, это приведет к путанице с людьми, ищущими getXXX –

+0

, это стиль Qt и java. http://qt.gitorious.org/qt/pages/ApiDesignPrinciples ---> goto «искусство именования» –

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++ безвозвратно разбит. Ни один человек не может разумно ожидать, что он будет разбирать, не говоря уже о написании этой строки кода правильно! –

+1

Хорошая точка. Перегрузка хороша сама по себе, но она мешает вам, когда вы хотите начать принимать адреса функций. - @mgb: Не стоит недооценивать людей. Можно также использовать 'std :: mem_fun_ref', но опять же из-за перегрузок необходимо указать типы:' std :: mem_fun_ref (& A :: Foo) '. – UncleBens

4

Я пойду вперед и отметить, что это должно быть сообщество вики вопрос.

Когда я начал изучать C++ я искал руководства по стилю, и Google был хорош для некоторых точек:

  • методы в верхнем регистре (это просто симпатичнее).
  • геттеры прямо и низкочастотные (rate).
  • сеттеры явно и в нижнем регистре (setRate).
+0

ОК - это был просто бесполезный кофе-брейк. –

2

Быть кратким важно, но не ценой неполного или вводящего в заблуждение. По этой причине я предпочитаю GetFoo() и SetFoo() для Foo() и Foo (int foo).

1

Лично я считаю, что геттеры и сеттеры, находящиеся в парах, представляют собой запах кода, переносимый с «визуальных» языков и их «свойств». В «хорошем» классе члены данных записываются только или только для чтения, но не для чтения/записи.

Я думаю, что самая распространенная причина геттеров и сеттеров не слишком хорошо переносит объектную модель. В вашем примере, почему общее время передается период и курс? Разве они не являются членами класса? Таким образом, вы должны устанавливать только период и скорость, и вы должны получать всего.

Возможно, есть исключения, но я просто ненавижу смотреть на класс и нахожу «getX/setX, getY/setY и т. Д. И т. Д.». Кажется, что недостаточно было подумать о том, как класс следует использовать, и, скорее, автор сделал класс EASY доступным для данных, поэтому ему не пришлось бы учитывать, как использовать класс.

Естественно, что я прав.

+0

Подумайте о трехмерном типе. Он будет иметь множество внутренних функций для выполнения различных математических упражнений, но в конечном итоге им понадобится все 6 функций get/set x/y/z. –

+0

@mgb: лично я не считаю, что трехмерный тип должен скрыть элементы в первую очередь (за исключением, возможно, потому, что вы можете использовать массив как внутреннее представление). – UncleBens

2

Есть несколько уровней, чтобы «Начало» и «Установка»

  • Я использую Get и Set для «быстрых» операций.
  • Если что-то займет больше времени для выполнения, то это часто будет Calc, так как эти имена подразумевают, что для получения результата необходимо выполнить некоторую работу.
  • Для более длинных операций, вы начнете получать в префиксы, как Load/Save, Query/магазин, чтение/запись, поиск/Найти и т.д.

Так 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 для MSVC? –

+1

@ Грег извините, я этого не делаю. Я действительно нахожу предупреждения MSVC (с VC8) в основном контрпродуктивными (предупреждение о производительности для преобразования между bool и int? Struct, ранее объявленное как класс?) Поскольку я строю на двух платформах, я обычно полагаюсь на gcc для всех моих предупреждения. – Tom

0

Я предпочитаю избегать меток 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 
+2

Вы не пишете значимых имен для компилятора, вы делаете это для другого программиста, который должен использовать ваш код. – Triskeldeian

+0

Пожалуйста, не думайте, что писать короткий/умный/сжатый код как-то автоматически лучше. Напишите код, чтобы вы и ваши сверстники знали, что происходит 6 месяцев спустя, не вытаскивая волосы. – nenchev

0

Если добытчик просто rate(), компилятор будет жаловаться, что его переопределение вашего другого rate символа, если вы дали свое поле хорошее значимое имя, как это. В этом случае вам нужно сделать что-то глупое, как имя вашего члена _rate или какой-либо другой подобный подход. Я лично ненавижу видеть/печатать эти символы подчеркивания, поэтому, как правило, придерживаюсь подхода getRate().

Это, очевидно, субъективно, и это, случается, является моим личным предпочтением.

Смежные вопросы