Pergunta

(Deixando de lado a questão de que você deve tê-los em tudo.)

Eu sempre preferiu função apenas uso sobrecarga para dar-lhe o mesmo nome para ambos getter e 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() );

Naturalmente, eu estou correto, mas eu me perguntava se os escritores biblioteca tinha nenhuma boa razão?

Foi útil?

Solução

Eu preferiria as versões get / set, porque é mais clara quanto ao que está acontecendo. Se eu taxa de serra () e taxa (10), como eu sei que a taxa (10) não está simplesmente usando 10 no cálculo para retornar a taxa? Eu não, então agora eu tenho para iniciar a pesquisa para descobrir o que está acontecendo. Um nome de função única deve fazer uma coisa, não duas coisas opostas.

Além disso, como os outros têm para fora pontas, alguns preferem omitir o 'ficar' e deixar o 'set', i.,

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

Esta convenção é bastante clara, bem, eu não teria qualquer problema ao ler isso.

Outras dicas

Eu sempre preferiu omitir o 'get' em meus getters, como você faz, com rate() vez de getRate(). Mas a sobrecarga para o setter não parece ser uma idéia muito boa para mim, já que o nome rate não transmitir que o objeto está sendo mutado. Considere o seguinte:

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?

Como cerca int rate(); e void setRate(int value);? Isto tem a virtude de não ter duas funções com o mesmo nome fazendo coisas diferentes, e ainda permite period() * rate().

Alguns anos atrás, eu teria concordado completamente. Mais recentemente, uma dúvida começou a fazer o seu caminho, porque isso faz tomar o endereço de um getter ou setter ambígua. Com ferramentas como tr1 :: bind, este é realmente irritante.

Por exemplo:

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

Deixando de lado a questão de que você deve tê-los em tudo; -)

Eu vou em frente e mencionar esta deve ser uma questão wiki comunidade.

Quando eu comecei a aprender C ++ Olhei para guias de estilo, e Google era bom para alguns pontos:

  • Métodos em maiúsculas (que é apenas mais bonita).
  • getters clara e quanto minúsculas (rate).
  • setters explicitamente e minúsculas (setRate).

Ser conciso é importante, mas não à custa de ser incompleta ou enganosa. Por essa razão, eu prefiro getFoo () e setFoo () para Foo () e Foo (int foo).

Existem vários níveis para "ficar" e "Setting"

  • Eu uso get e set de "fast" operações.
  • Se algo vai demorar mais tempo para executar, então ele vai muitas vezes ser um Calc, como esses nomes sugerem que algum trabalho tem que ser feito para recuperar o resultado.
  • Para operações mais longas, você começa a entrar em prefixos como Load / Save, Consulta / loja, Read / Write, Pesquisa / Encontrar etc.

Assim GET / SET pode ser atribuído um significado útil, e ser parte de uma estratégia de nomenclatura consistente maior.

Enquanto o comentário de Ed é verdade, eu prefiro propriedades reais sobre o setter / getter antipattern. Quando 1 / 3rd dos métodos em seu domínio gráfico são métodos fictícios que foram gerados pelo eclipse, há algo errado.

Sem propriedades de primeira classe, no entanto, acredito que o antipattern faz mais sentido.

Além disso, torna a conclusão de código mais fácil.

obj.set (control shift space) para setters
obj.get (control shift space) para getters

Pessoalmente, acho que getters e setters encontrados em pares são um cheiro de código transitadas de línguas "visual" e suas "propriedades". Em um "bom" classe, os membros de dados são writeonly ou somente leitura, mas não de leitura / gravação.

Eu acho que a causa mais comum de getters e setters não está carregando o modelo de objeto profundidade suficiente. No seu exemplo, porque é que ser total passou o período ea taxa? Eles não são membros da classe? Então você só deve ser definir o período ea taxa e você só deve estar recebendo um total.

Há provavelmente exceções, mas eu odeio olhando para uma classe e encontrar "getX / setX, getY / setY, etc. etc." Parece apenas não foi o suficiente pensado em como deve ser utilizada a classe e sim o autor fez a classe fácil de obter para os dados para que ele não tem que considerar como a classe deve ser usado.

Naturalmente estou correto.

Outra questão que ninguém tenha mencionado é o caso de sobrecarga de funções. Veja este exemplo (artificial e incompleto):

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

Sem essa cláusula using, os usuários de Contractor não pode consultar o salário por causa da sobrecarga. Recentemente adicionado -Woverloaded-virtual ao conjunto de alerta de um trabalho de projecto I, e eis que, este mostrou-se por todo o lugar.

Eu impor a convenção em que um método deve ser sempre um verbo e uma classe deve sempre ser um substantivo (exceto para functors, por razões óbvias). Nesse caso, um get / set prefixo deve ser utilizado para a consistência. Dito isto, eu também concordo inteiramente com Ed Swangren. Isto resume a mim como usar esses prefixos um acéfalo.

Eu prefiro evitar os obter e definir rótulos, a informação não é necessário para o compilador para fazer seu trabalho para a maioria dessas propriedades simples.

você pode ter problemas:

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

Se o seu getter é simplesmente rate(), o compilador iria reclamar que a sua redefinição do seu outro símbolo rate, desde que você deu seu campo um bom nome significativo assim. Nesse caso, você precisa fazer alguma coisa boba como nome o seu _rate membro ou alguma outra abordagem semelhante. Eu, pessoalmente, odeio ver / digitando essas sublinhados, por isso, tendem a ir com a abordagem getRate().

Esta é, obviamente, subjetiva e isso só acontece de ser a minha preferência pessoal.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top