Usando getters públicos em vez de privados

47

Eu vejo os POJOs mais imutáveis escritos assim:

public class MyObject {
    private final String foo;
    private final int bar;

    public MyObject(String foo, int bar) {
        this.foo = foo;
        this.bar = bar;
    }

    public String getFoo() {
        return foo;
    }

    public int getBar() {
        return bar;
    }
}

Ainda tenho a tendência de escrevê-los assim:

public class MyObject {
    public final String foo;
    public final int bar;

    public MyObject(String foo, int bar) {
        this.foo = foo;
        this.bar = bar;
    }
}

Note que as referências são finais, então o objeto ainda é imutável. Ele permite que eu escreva menos código e permite acesso mais curto (por 5 caracteres: o get e () ).

A única desvantagem que posso ver é se você quer mudar a implementação de getFoo() no caminho para fazer algo louco, você não pode. Mas, realisticamente, isso nunca acontece porque o objeto é imutável; você pode verificar durante a instanciação, criar cópias defensivas imutáveis durante a instanciação (consulte% de ImmutableList da Goiaba, por exemplo) e obter os objetos foo ou bar prontos para a chamada get .

Há alguma desvantagem que está faltando?

EDITAR

Suponho que outra desvantagem que estou perdendo são as bibliotecas de serialização usando a reflexão sobre os métodos que começam com get ou is , mas essa é uma prática bastante terrível ...

    
por Cory Kendall 18.03.2013 / 02:00
fonte

4 respostas

36

Quatro desvantagens que posso pensar:

  1. Se você deseja ter uma forma somente leitura e mutável da mesma entidade, um padrão comum é ter uma classe imutável Entity que expõe somente acessadores com variáveis de membro protegidas e, em seguida, criar um MutableEntity que estende e adiciona setters. Sua versão impede isso.
  2. O uso de getters e setters adere à convenção JavaBeans. Se você quiser usar sua classe como um bean em tecnologias baseadas em propriedade, como JSTL ou EL, precisará expor public getters.
  3. Se você quiser alterar a implementação para derivar os valores ou procurá-los no banco de dados, será necessário refatorar o código do cliente. Uma abordagem acessadora / mutadora permite que você apenas altere a implementação.
  4. Menos espanto - quando vejo variáveis de instância públicas, eu imediatamente procuro por quem pode estar sofrendo uma mutação e me preocupo se estou abrindo a caixa de Pandora porque o encapsulamento está perdido. link

Dito isto, a sua versão é definitivamente mais concisa. Se esta fosse uma classe especializada que é usada apenas dentro de um pacote específico (talvez o escopo do pacote seja uma boa idéia aqui), então eu posso considerar isso para one-offs. Mas eu não iria expor grandes APIs como esta.

    
por 18.03.2013 / 02:57
fonte
24

Livre-se dos getters / setters também, e você está bem!

Este é um tópico altamente controverso entre os programadores de Java.

De qualquer forma, há duas situações onde eu uso variáveis públicas (!) de getters / setters:

  1. final público Para mim isso sinaliza "sou imutável" muito melhor do que apenas um getter. A maioria dos IDEs indicará o modificador final com um 'F' durante o preenchimento automático. Ao contrário dos getters / setters, onde você deve procurar a ausência de um setXXX.
  2. público não final Adoro isso para classes de dados. Eu apenas exponho todos os campos publicamente. Não há getters, setters, construtores. Não há nada. Menos que um pojo. Para mim isso imediatamente sinaliza "olha, eu sou burro. Eu seguro os dados, isso é tudo. É SUA tarefa colocar os dados certos dentro de mim". Gson / JAXB / etc. lidar com essas classes muito bem. Eles são uma felicidade para escrever. Não há dúvidas sobre seu propósito ou capacidades. E o mais importante: você sabe que não há efeitos colaterais quando você altera uma variável. IMHO isso resulta em modelos de dados muito concisos com poucas ambiguidades, enquanto os getters e setters têm esse enorme problema onde às vezes a mágica acontece dentro deles.
por 05.11.2014 / 19:17
fonte
9

Em palavras de leigo:

  • Você violar o encapsulamento para salvar algumas linhas de código. que derrota o propósito do OOD.
  • O código do cliente será acoplado com força aos nomes dos membros da sua turma. O acoplamento é ruim. Todo o propósito do OOD está impedindo o acoplamento.
  • Você também está muito certo de que sua classe nunca precisará ser mutável. As coisas mudam. A mudança é a única coisa que é constante.
por 28.05.2013 / 16:31
fonte
6

Uma possível desvantagem que posso ver de improviso é que você está preso à representação interna dos dados na classe. Isso provavelmente não é um grande problema, mas se você usar os setters e decidir que foo e bar serão retornados de alguma outra classe definida em algum outro lugar, as classes que consomem MyObject não precisarão ser alteradas. Você só precisa tocar em MyObject. No entanto, se você usar os valores nus, então você teria que tocar em todos os lugares que o MyObject i usou.

    
por 18.03.2013 / 02:38
fonte