Eu tenho uma classe com uma variável que é privada e a classe tem um getter e um setter para essa variável. Por que não tornar pública essa variável?
O único caso em que acho que você precisa usar getters e setters é se precisar fazer alguma operação além do set ou do get. Exemplo:
void my_class::set_variable(int x){
/* Some operation like updating a log */
this->variable = x;
}
c++
encapsulation
setters
Oni
fonte
fonte
this->variable = x + 5
ou chamar umaUpdateStatistics
função no setter e, nesses casosclassinstancea->variable = 5
, causará problemas.set_inch
,set_centimeter
,get_inch
,get_centimeter
, com algumas ações assustadores.Respostas:
Você já ouviu falar sobre uma propriedade?
Uma propriedade é um campo que possui acessadores "internos" (getters e setters). Java, por exemplo, não possui propriedades, mas é recomendável gravar os getters e setters em um campo privado. C # tem propriedades.
Então, por que precisamos de getters e setters? Basicamente, precisamos dela para proteger / proteger o campo. Por exemplo, você não está acessando o campo na referência de memória, está acessando um método que alterará o campo (referência). Esse método é capaz de executar algumas operações que um usuário não está disposto a conhecer ( comportamento de encapsulamento ), como no seu exemplo. Imagine, por exemplo, que uma dúzia de classes use seu campo público e você precise alterar a maneira como é usado ... Você precisaria examinar cada uma dessas classes para alterar a maneira como elas estão usando o campo ... Não então "OOlysh".
Mas, por exemplo, se você tiver um campo booleano chamado dead. Você deve pensar duas vezes antes de declarar um setDead e um isDead. Você deve escrever acessadores legíveis por humanos , por exemplo, kill () em vez de setDead.
No entanto, existem muitas estruturas que assumem que você está seguindo a convenção de nomenclatura JavaBean (falando sobre Java aqui); portanto, nesses casos, você deve declarar todos os getters e setters após a convenção de nomenclatura.
fonte
foo.bar = biz.baz+5
uma função seja chamadabiz
para avaliarbaz
, adicione cinco a ela e chame uma funçãofoo
para definirbar
o valor resultante. Tais sobrecargas não são chamadas de "propriedades", mas podem servir ao mesmo objetivo.Esta não é a opinião mais popular, mas não vejo muita diferença.
Setters e getters são uma péssima idéia. Eu pensei sobre isso e honestamente não consigo chegar a uma diferença entre um levantador / levantador de uma propriedade e uma variável pública na prática.
Em THEORY, um setter e getter ou propriedade adicionam um local para executar algumas ações extras quando uma variável é configurada / obtida e, em teoria, eles isolam seu código de alterações.
Na realidade, raramente vejo setters e getters usados para adicionar uma ação, e quando você deseja adicionar uma ação, você deseja adicioná-la a TODOS os setters ou getters de uma classe (como log), o que deve fazer você pensar que deve ser uma solução melhor.
Quanto ao isolamento das decisões de projeto, se você alterar um int por muito tempo, ainda precisará alterar seus setters e, pelo menos, verificar todas as linhas que os acessam manualmente - não há muito isolamento lá.
As classes mutáveis devem ser evitadas por padrão de qualquer maneira, portanto, adicionar um setter deve ser o último recurso. Isso é mitigado com o padrão do construtor, em que um valor pode ser definido até que o objeto esteja no estado desejado, para que a classe se torne imutável e seus configuradores lançem exceções.
Quanto aos getters - ainda não consigo encontrar muita diferença entre um getter e uma variável final pública. O problema aqui é que é ruim OO em ambos os casos. Você não deve estar pedindo um valor a um objeto e operando nele - você deve estar pedindo a um objeto que faça uma operação para você.
A propósito, não estou de maneira alguma defendendo variáveis públicas - estou dizendo que setters e getters (e até propriedades) estão muito perto de já serem variáveis públicas.
O grande problema é simplesmente que as pessoas que não são programadores de OO ficam tentadas a usar setters e getters para transformar objetos em bolas de propriedades (estruturas) que são passadas e operadas, praticamente o oposto de como o código orientado a objetos funciona.
fonte
O usuário de getters e setters entra no princípio do encapsulamento . Isso permitirá que você altere como as coisas funcionam dentro da classe e mantenha tudo funcionando.
Por exemplo, se três outros objetos chamarem
foo.bar
para obter o valor da barra e você decidir alterar o nome da barra para longe, terá um problema em suas mãos. Se os objetos chamados,foo.bar
você teria que alterar todas as classes que possuem isso. Se um setter / getter for usado, você não terá nada para mudar. Outra possibilidade é alterar o tipo da variável; nesse caso, basta adicionar algum código de transformação ao getter / setter e você estará bem.fonte
O uso de getters e setters também permite controlar o conteúdo que é armazenado em uma variável específica. Se o conteúdo precisar ser de um determinado tipo ou valor, parte do seu código de configuração pode garantir que o novo valor atenda a esses requisitos. Se a variável for pública, não será possível garantir que esses requisitos sejam atendidos.
Essa abordagem também torna seu código mais adaptável e gerenciável. É muito mais fácil fazer alterações na arquitetura de uma classe se você tiver funções que mantêm essa arquitetura oculta de todas as outras classes ou funções que utilizam essa classe. A mudança já mencionada de um nome de variável é apenas uma das muitas mudanças que são muito mais fáceis de fazer se você tiver funções como getters e setters. A idéia geral é manter o máximo de privacidade possível, especialmente as variáveis de classe.
fonte
Você diz "O único caso em que acho que você precisa usar getters e setters é se você precisar fazer alguma operação além do set ou do get".
Você deve usar getters e setters se em algum momento no futuro, você pode precisar fazer alguma operação além do set e get e você não deseja alterar milhares de linhas de código-fonte, quando isso acontece.
Você deve usar getters e setters se não quiser que alguém pegue o endereço da variável e o repasse, com conseqüências desastrosas se essa variável puder ser alterada sem nenhum código fonte mencioná-la ou mesmo depois que o objeto deixar de existir. .
fonte
Primeiro, vamos deixar claro o paradigma.
Onde um getter / setter é útil?
Os getters / setters são úteis nas estruturas de dados? Não.
Uma estrutura de dados é uma especificação de layout de memória comum e manipulada por uma família de funções.
Geralmente, qualquer nova função antiga pode surgir e manipular uma estrutura de dados, se o fizer de uma maneira que as outras funções ainda possam entendê-la, então a função se juntará à família. Caso contrário, é uma função desonesta e uma fonte de bugs.
Não me interpretem mal, poderia haver várias famílias de funções lutando sobre essa estrutura de dados com delatores, casacos de turno e agentes duplos em todos os lugares. Tudo bem quando cada um tem sua própria estrutura de dados para brincar, mas quando o compartilha ... imagine várias famílias de criminosos discordando sobre política, pode se tornar uma bagunça muito rápida.
Dada a bagunça que as famílias de funções estendidas podem alcançar, existe uma maneira de codificar a estrutura de dados para que as funções não autorizadas não estraguem tudo? Sim, eles são chamados de objetos.
Os getters / setters são úteis nos objetos? Não.
O objetivo de agrupar uma estrutura de dados em um objeto era garantir que nenhuma função invasora pudesse existir. Se a função quisesse se juntar à família, ela teria que ser cuidadosamente examinada primeiro e depois se tornar parte do objeto.
O objetivo / objetivo de um getter e de um setter é permitir que funções fora do objeto alterem diretamente o layout da memória do objeto. Isso soa como uma porta aberta para permitir que bandidos ...
The Edge Case
Existem duas situações em que um getter / setter público faz sentido.
Contêineres e interfaces de contêiner são exemplos perfeitos dessas duas situações. O contêiner gerencia internamente as estruturas de dados (lista vinculada, mapa, árvore), mas passa o controle sobre o elemento específico para todos. A interface abstrai isso e ignora completamente a implementação e descreve apenas as expectativas.
Infelizmente, muitas implementações entendem isso errado e definem a interface desses tipos de objetos para fornecer acesso direto ao objeto real. Algo como:
Isto está quebrado. As implementações do Container devem entregar explicitamente o controle de seus internos a quem os usar. Ainda não vi uma linguagem de valor mutável em que isso seja bom (linguagens com semântica de valor imutável são, por definição, ótimas do ponto de vista de corrupção de dados, mas não necessariamente do ponto de vista de espionagem de dados).
Você pode melhorar / corrigir os getters / setter usando apenas cópia semântica ou usando um proxy:
Indiscutivelmente, uma função não autorizada ainda pode causar confusão aqui (com esforço suficiente, a maioria das coisas é possível), mas a cópia-semântica e / ou proxy reduz a chance de vários erros.
Getters / Setters privados
Este é o último bastião de getters e setters trabalhando diretamente no tipo. Na verdade, eu nem chamaria esses getters e setters, mas acessores e manipuladores.
Nesse contexto, às vezes, manipular uma parte específica da estrutura de dados sempre / quase sempre / geralmente exige que ocorra manutenção contábil específica. Digamos que quando você atualiza a raiz de uma árvore, o cache oculto precisa ser eliminado ou quando você acessa o elemento de dados externos, um bloqueio precisa ser obtido / liberado. Nesses casos, faz sentido aplicar o principal DRY e agrupar essas ações.
Dentro do contexto privado, ainda é possível para as outras funções da família desviar esses 'getters e setters' e manipular a estrutura de dados. Por isso, penso neles mais como acessores e manipuladores. Você pode acessar os dados diretamente ou confiar em outro membro da família para acertar essa parte.
Getters / Setters protegidos
Em um contexto protegido, não é muito diferente de um contexto público. Funções estrangeiras possivelmente desonestas desejam acessar a estrutura de dados. Portanto, não, se existem, eles operam como getters / setters públicos.
fonte
Por experiência em C ++, o setter / getter é útil para 2 cenários:
Além disso, a segurança é um ponto válido, mas sua importância é limitada a muito poucos aplicativos de desenvolvimento, como módulos relacionados ao login ou acesso ao banco de dados. Por que se preocupar em codificar extra quando apenas poucas pessoas usam seu módulo?
fonte