Pergunta

Esta questão já tem uma resposta aqui:

Atualmente estou trabalhando em um jogo simples em Java com vários modos diferentes. Eu estendeu uma classe jogo principal para colocar a lógica principal dentro das outras classes. Apesar disso, a classe principal do jogo ainda é bastante robusto.

Depois de tomar um rápido olhar para o meu código a maioria do que foi Getters e Setters (60%) em comparação com o resto que é realmente necessário para a lógica do jogo.

Um par de pesquisas do Google afirmaram que getters e setters são maus, enquanto outros afirmam que eles são necessários para uma boa prática OO e grandes programas.

Então, o que devo fazer? Que deve ser? Devo estar mudando meus getters e setters para os meus variáveis ??privadas, ou devo ficar com eles?

Foi útil?

Solução

Há também o ponto de vista que a maior parte do tempo, usando setters ainda quebra o encapsulamento, permitindo que você defina valores que são sem sentido. Como um exemplo muito óbvio, se você tem um contador de pontuação no jogo que só nunca sobe, em vez de

// Game
private int score;
public void setScore(int score) { this.score = score; }
public int getScore() { return score; }
// Usage
game.setScore(game.getScore() + ENEMY_DESTROYED_SCORE);

deve ser

// Game
private int score;
public int getScore() { return score; }
public void addScore(int delta) { score += delta; }
// Usage
game.addScore(ENEMY_DESTROYED_SCORE);

Esta é, talvez, um pouco de um exemplo fácil. O que eu estou tentando dizer é que discutir getter / setters vs campos públicos muitas vezes obscurece maiores problemas com objetos manipular estado interno uns dos outros de uma maneira íntima e, portanto, a ser demasiado estreitamente associadas.

A idéia é fazer com que os métodos que fazem diretamente coisas que você quer fazer. Um exemplo seria como inimigos Definir status 'vivo'. Você pode ser tentado a ter um método (boolean alive) setAlive. Em vez disso você deve ter:

private boolean alive = true;
public boolean isAlive() { return alive; }
public void kill() { alive = false; }

A razão para isto é que se você alterar a implementação de que as coisas já não têm um "vivo" boolean mas sim um valor "pontos de vida", você pode mudar isso sem quebrar o contrato dos dois métodos que você escreveu anteriormente:

private int hp; // Set in constructor.
public boolean isAlive() { return hp > 0; } // Same method signature.
public void kill() { hp = 0; } // Same method signature.
public void damage(int damage) { hp -= damage; }

Outras dicas

  • Muito mal:. Campos públicos
  • Um pouco mal:. Getters e setters onde eles não estão obrigados
  • Bom: Getters e setters apenas quando eles estão realmente necessários - fazer o tipo expor comportamento "maior" que acontece de uso seu estado, em vez de apenas tratar o tipo como um repositório de estado para ser manipulado por outros tipos.

É realmente depende da situação embora -. Às vezes você realmente não quer apenas um objeto de dados mudo

Você já tinha um monte de boas respostas sobre isso, então eu vou apenas dar meus dois centavos. Getters e setters são muito, muito mal. Eles essencialmente permitem que você fingir para esconder internos do seu objeto, quando na maioria das vezes tudo que você fez é lançado em código redundante que não faz nada para o estado interno esconder. Para um POJO simples, não há nenhuma razão para que getName () e setName () não pode ser substituído por obj.name = "Tom".

Se a chamada de método apenas substitui atribuição, então tudo o que você ganhou, preferindo a chamada de método é bloat código. Infelizmente, a linguagem tem consagrado o uso de getters e setters na especificação JavaBeans, para que os programadores Java são obrigados a usá-los, mesmo quando isso não faz qualquer sentido.

Felizmente, Eclipse (e provavelmente outros IDEs também) permite gerar automaticamente. E para um projeto divertido, uma vez eu construiu um gerador de código para eles em XSLT. Mas se há uma coisa que eu me livraria em Java, é o excesso de dependência de getters e setters.

Getters e setters impor o conceito de encapsulamento na programação orientada a objeto.

Por ter os estados do objeto escondido do mundo exterior, o objeto é realmente responsável por si mesmo, e não pode ser alterada de maneiras que não se destinam. As únicas formas que o objeto pode ser manipulado são através de métodos públicos expostos, como getters e setters.

Existem algumas vantagens para ter getters e setters:

1. Permitindo mudanças futuras sem modificações ao código que usa a classe modificada.

Uma das grandes vantagens de usar um getter e setter é que uma vez que os métodos públicos são definidos e chega um momento em que os subjacentes necessidades de implementação a ser alterado (por exemplo, encontrar um bug que precisa ser corrigido, usando um algoritmo diferente para melhorar o desempenho, etc.), tendo os getters e setters ser a única maneira de manipular o objeto, ele irá permitir que o código existente para não quebrar, e trabalhar como esperado, mesmo depois da alteração.

Por exemplo, digamos que há um método setValue que define o value variável privada em um objeto:

public void setValue(int value)
{
    this.value = value;
}

Mas, em seguida, houve um novo requisito que necessário para manter o controle do número de vezes value foi alterado. Com o setter no lugar, a mudança é bastante trivial:

public void setValue(int value)
{
    this.value = value;
    count++;
}

Se o campo value eram públicos, não há nenhuma maneira fácil de voltar mais tarde e adicionar um contador que mantém o controle do número de vezes que o valor foi alterado. Portanto, ter getters e setters são uma forma de "à prova de futuro" a classe para mudanças que podem vir mais tarde.

2. Impondo os meios pelos quais o objecto pode ser manipulado.

Outra maneira getters e setters vir a calhar é para fazer cumprir as formas do objeto podem ser manipulados, portanto, o objeto está no controle de seu próprio estado. Com variáveis ??públicas de um objeto exposto, ele pode ser facilmente corrompido.

Por exemplo, um objecto ImmutableArray contém uma matriz int chamado myArray. Se a matriz fosse um campo público, ele só não vai ser imutável:

ImmutableArray a = new ImmutableArray();
int[] b = a.myArray;
b[0] = 10;      // Oops, the ImmutableArray a's contents have been changed.

Para implementar uma matriz verdadeiramente imutável, um getter para a matriz (método getArray) deve ser escrito para que ele retorna uma cópia da sua matriz:

public int[] getArray()
{
    return myArray.clone();
}

E mesmo se ocorre o seguinte:

ImmutableArray a = new ImmutableArray();
int[] b = a.getArray();
b[0] = 10;      // No problem, only the copy of the array is affected.

O ImmutableArray é de fato imutável. Expondo as variáveis ??de um objeto vai permitir que ele seja manipulado de maneira que não se destinam, mas apenas expor certas maneiras (getters e setters), o objeto pode ser manipulado de forma pretendidos.

suponho ter getters e setters seria mais importante para as classes que fazem parte de uma API que vai ser utilizada por outras pessoas, pois permite manter a API intacta e inalterada, permitindo alterações na aplicação subjacente.

Com todas as vantagens de getters e setters disse, se o getter é simplesmente devolver o valor da variável privada e o setter é meramente aceitar um valor e atribuí-la a uma variável privada, parece que os getters e setter são apenas estranhos e realmente um desperdício. Se a classe vai ser apenas para uso interno por um aplicativo que não vai ser usado por outros, usando getters e setters extensivamente pode não ser tão importante como quando se escreve uma API pública.

Eles são absolutamente mal.

@coobird, infelizmente, eles absolutamente não "impor o conceito de encapsulamento", todos eles fazem é fazer você pensar que você está encapsulando dados quando na verdade você está expondo dados via uma propriedade com delírios de grandeza método. Qualquer coisa que um getter / setter faz um campo público faz melhor.

Em primeiro lugar, se você quiser dados públicos, torná-la pública, se livrar dos métodos getter e setter para reduzir o número de métodos que o cliente tem de percorrer e torná-lo cognitivamente mais simples para o cliente para mudá-lo de valor, por exemplo.

object.field = value;

em vez do cognitivamente mais intensa

object.setField(value);

onde o cliente deve agora verificar o método getter / setter para ver se ele tem quaisquer efeitos colaterais.

Em segundo lugar, se você realmente precisa fazer algo mais no método, por que chamá-lo de / set método get quando se tem mais responsabilidades do que simplesmente obter ou configuração? Ou seguir o SRP ou chamar o método algo que realmente lhe diz o que o todo método faz como exemplos de Zarkonnen ele mencionou por exemplo.

public void kill(){
    isAlive = false;
    removeFromWorld(this);
}

em vez de

public void setAlive(boolean isAlive){
    this.isAlive = isAlive;
    if (isAlive)
        addToWorld(this);
    else
        removeFromWorld(this);
}

onde é que o método setAlive (boolean) dizer ao cliente que, como um efeito colateral que vai remover o objeto do mundo? Por que o cliente tem qualquer conhecimento sobre o campo isAlive? Além disso, o que acontece quando o objeto é adicionado novamente para o mundo, deveria ser re-inicializado? por que o atendimento ao cliente com nada disso?

IMHO a moral é nomear métodos para dizer exatamente o que eles fazem, seguir o SRP e se livrar de getters / setters. Se há problemas sem getters / setters, diga objetos para fazer o seu próprio trabalho sujo dentro de sua própria classe, em vez de tentar fazer as coisas com eles em outras classes.

Aqui termina meu discurso, desculpe sobre isso;)

É uma ladeira escorregadia.

Um simples objeto de transferência (ou objeto de parâmetro) pode ter o único propósito de manter alguns campos e fornecer seus valores sob demanda. No entanto, mesmo nesse caso degenerado pode-se argumentar que o objeto deve ser imutável -. Configurado no construtor e expondo apenas get ... métodos

Há também o caso de uma classe que expõe alguns "botões de controle"; UI do seu rádio de carro, provavelmente pode ser entendida como expor algo como getVolume, setVolume, getChannel e setChannel, mas sua funcionalidade real está recebendo sinais e emitindo som. Mas esses botões não exponha tanto detalhe de implementação; você não sabe a partir desses recursos de interface se o rádio está transistores, principalmente em software, ou tubos de vácuo.

Quanto mais você começar a pensar em um objeto como um participante ativo em uma tarefa problema-domínio, o mais você pensar em termos de pedindo-lhe para fazer algo em vez de pedir-lo para contar -lo sobre seu estado interno, ou pedindo-lhe para seus dados de modo outro código pode fazer algo com esses valores.

Então ... "mal"? Na verdade não. Mas cada vez que você está inclinado a colocar em um valor e expor tanto get ... e set ... métodos sobre esse valor, pergunte-se por que, eo que isso reponsibility do objeto realmente é. Se a única resposta que você pode dar a si mesmo é: "Para manter este valor para mim", então talvez algo além de OO está acontecendo aqui.

Sua classe jogo é provavelmente seguindo o deus objeto antipattern se expõe que muitas variáveis. Não há nada de errado com getters e setters (embora a sua verbosidade em Java pode ser um pouco chato); em um aplicativo bem projetado, onde cada classe tem uma funcionalidade claramente separados, você não vai precisar dezenas deles em uma única classe.

Editar: Se o ponto principal para os getters e setters é "configure" a classe jogo (eu entendo o seu comentário de que maneira), então o seu provavelmente não precisa os getters (é perfeitamente bem para uma classe para acessar suas próprias variáveis ??privadas sem usar métodos get), e provavelmente você pode entrar em colapso muitos dos setters em "setters grupo" que estabelecem uma série de variáveis ??que pertencem juntos conceitualmente.

A presença de getter e setters tende a indicar (um "cheiro" se você estiver em que tipo de linguagem escola primária) que há um problema de projeto. getters triviais e setters são mal distinguíveis de campos públicos. Normalmente, o funcionamento do código sobre os dados estarão em uma classe diferente -. Pobre encapsulamento, eo que você esperaria de programadores não à vontade com OO

Em alguns casos getters e setters são muito bem. Mas, como regra um tipo com ambas getters e setters indica problemas de design. Getters trabalhar para imutabilidade; setters trabalhar para "dizer não pergunte". Ambos imutabilidade e "dizer não pergunte" são boas escolhas de design, desde que não sejam aplicadas de um estilo de sobreposição.

A minha opinião é que getters e setters são um requisito para bons programas. Vara com eles, mas não escrever getters desnecessários / setters -. Nem sempre é necessário para lidar diretamente com todas as variáveis ??

Eu realmente não acho que eles são maus. Mas eu gostaria de viver em um mundo onde eu nunca tive que usá-los a menos que eu realmente precisava.

Um exemplo que leu acima foi future-proofing seu código. Por exemplo:

public void setValue(int value)
{
    this.value = value;
}

Em seguida, os requisitos mudam e você precisa controlar quantas vezes o valor foi definido.

Assim:

public void setValue(int value)
{
    this.value = value;
    count++;
}

Esta é bonito. Entendi. No entanto, em Ruby, seria o seguinte não têm a mesma finalidade?

someobject.my_value = 100

Mais tarde, você precisa controlar o número de vezes my_value foi definida. Bem, então, você poderia não apenas substituir o setter THEN e só THEN ?

def my_value=(value)
    @my_value = value
    @count++
end

Eu sou tudo para código bonito, mas eu tenho que admitir, olhando através das montanhas de classes Java que temos e ver literalmente milhares e milhares de linhas de código que não são nada, mas getter básico / setters é feio e chato.

Quando eu estava desenvolvendo em C # tempo integral, usamos propriedades públicas o tempo todo e fez getters personalizados / única setters quando necessário. Trabalhou como um encanto e não quebrar nada.

Como sempre, a única resposta é: depende. Se você é o único peron tocar no código, você pode fazer qualquer coisa que você está confortável, incluindo tomar atalhos.

Um dos benefícios de usar setters é que os controlos devem ser realizados em apenas um local em seu código.

Você pode querer pagar alguns mais atenção ao que está realmente sendo get e set por estes métodos. Se você estiver usando-os para fornecer acesso aos valores constantes que você é provavelmente melhor fora usando constantes.

Isso depende da linguagem de programação em questão. Sua pergunta é enquadrada no contexto de Java, onde parece que getters e setters são geralmente consideradas como uma coisa boa.

Em contraste, no mundo Python, eles são geralmente considerados como mau estilo: eles adicionar linhas ao código sem realmente adicionando funcionalidade. Quando os programadores Python precisa, eles podem usar metaprogramming para pegar recebendo e / ou a criação de atributos de objeto.

Em Java (pelo menos a versão do Java que eu aprendi um pouco de uma década atrás), que não era possível. Assim, em Java geralmente é melhor usar getters e setters religiosamente, de modo que se você precisar, você pode substituir o acesso às variáveis.

(Isso não faz Python necessariamente melhor do que Java, apenas diferente.)

Apenas FYI: Além de todas as excelentes respostas neste segmento, lembre-se que de todas as razões que você pode vir acima com a favor ou contra getters / setters, o desempenho não é um (como alguns podem acreditar). A JVM é inteligente o suficiente para inline getters triviais / (mesmo os não-final, contanto que eles não são realmente substituído) setters.

Você pode querer substituir algumas de suas aulas por classes de valor. Isso permitirá que você para remover os problemas getter e evitar quando o conteúdo é alterado debaixo de você.

Se você precisa de acesso externo para valores individuais de campos, use getters e / ou setters. Se não, não. Nunca use campos públicos. É simples assim! (Ok, nunca é que simples, mas é uma boa regra de ouro).

Em geral, você também deve saber que você precisa fornecer um setter muito menos frequentemente do que um getter - especialmente se você está tentando fazer seus objetos imutáveis ??- que é uma coisa boa (mas não sempre a melhor escolha) - mas mesmo se não.

Eu tenho programado em Java para alguns meses atrás, e eu aprendi que devemos usar getters e setters apenas quando é necessário para a aplicação

se divertir:)

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