Você deve usar getters e setters quando:
- Você está lidando com algo que é conceitualmente um atributo, mas:
- Seu idioma não possui propriedades (ou algum mecanismo semelhante, como os traços variáveis de Tcl) ou
- O suporte à propriedade do seu idioma não é suficiente para este caso de uso ou
- As convenções idiomáticas do seu idioma (ou às vezes do seu framework) incentivam getters ou setters para este caso de uso.
Portanto, raramente é uma questão geral de OO; é uma pergunta específica de idioma, com respostas diferentes para idiomas diferentes (e diferentes casos de uso).
Do ponto de vista da teoria do OO, getters e setters são inúteis. A interface da sua classe é o que ela faz, não o seu estado. (Caso contrário, você escreveu a classe errada.) Em casos muito simples, onde o que uma classe faz é apenas, por exemplo, representar um ponto em coordenadas retangulares, * os atributos fazem parte da interface; getters e setters apenas obscurecem isso. Mas, em qualquer coisa, exceto em casos muito simples, nem os atributos, nem os getters e setters fazem parte da interface.
Dito de outra forma: se você acredita que os consumidores de sua classe nem deveriam saber que você tem um spam
atributo, muito menos poder alterá-lo à vontade, então dar a eles um set_spam
método é a última coisa que você deseja fazer.
* Mesmo para essa classe simples, talvez você não queira permitir a definição dos valores x
e y
. Se isso é realmente uma classe, não deveria ter métodos como translate
,rotate
, etc.? Se é apenas uma aula porque seu idioma não possui registros / estruturas / tuplas nomeadas, isso não é realmente uma questão de OO…
Mas ninguém nunca faz o projeto geral de OO. Eles estão fazendo design e implementação em um idioma específico. E em alguns idiomas, getters e setters estão longe de serem inúteis.
Se o seu idioma não tiver propriedades, a única maneira de representar algo que é conceitualmente um atributo, mas na verdade é computado, ou validado etc. é através de getters e setters.
Mesmo que seu idioma tenha propriedades, pode haver casos em que sejam insuficientes ou inapropriados. Por exemplo, se você deseja permitir que as subclasses controlem a semântica de um atributo, em idiomas sem acesso dinâmico, uma subclasse não poderá substituir uma propriedade computada por um atributo.
Quanto ao "e se eu quiser alterar minha implementação mais tarde?" question (que é repetido várias vezes com palavras diferentes na pergunta do OP e na resposta aceita): Se realmente é uma alteração pura na implementação e você começou com um atributo, pode alterá-lo para uma propriedade sem afetar a interface. A menos, é claro, que seu idioma não suporte isso. Portanto, esse é realmente o mesmo caso novamente.
Além disso, é importante seguir os idiomas da linguagem (ou estrutura) que você está usando. Se você escrever um belo código no estilo Ruby em C #, qualquer desenvolvedor experiente em C # que não seja você terá problemas para lê-lo, e isso é ruim. Algumas linguagens têm culturas mais fortes em torno de suas convenções do que outras. - e pode não ser coincidência que Java e Python, que estão em extremos opostos do espectro de como são os geters idiomáticos, possuam duas das culturas mais fortes.
Além dos leitores humanos, haverá bibliotecas e ferramentas que esperam que você siga as convenções e torne sua vida mais difícil se não o fizer. Conectar os widgets do Interface Builder a qualquer coisa, exceto propriedades ObjC, ou usar determinadas bibliotecas de simulação Java sem getters, está apenas dificultando sua vida. Se as ferramentas são importantes para você, não lute contra elas.