Usando final pública en lugar de captadores privados

47

Veo los POJO más inmutables escritos de esta forma:

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

Sin embargo, tiendo a escribirlos así:

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

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

Tenga en cuenta que las referencias son finales, por lo que el objeto sigue siendo inmutable. Me permite escribir menos código y permite un acceso más corto (por 5 caracteres: get y () ).

La única desventaja que puedo ver es que si quieres cambiar la implementación de getFoo() en el futuro para hacer algo loco, no puedes. Pero de manera realista, esto nunca sucede porque el Objeto es inmutable; puede verificar durante la creación de instancias, crear copias defensivas inmutables durante la ejemplificación (consulte el ejemplo de ImmutableList de Guava) y obtener los objetos foo o bar listos para la llamada get .

¿Hay alguna desventaja que me esté perdiendo?

EDIT

Supongo que otra desventaja que me falta es que las bibliotecas de serialización utilizan la reflexión sobre los métodos que comienzan con get o is , pero esa es una práctica bastante terrible ...

    
pregunta Cory Kendall 18.03.2013 - 02:00

4 respuestas

36

Cuatro desventajas que se me ocurren:

  1. Si desea tener una forma de solo lectura y mutable de la misma entidad, un patrón común es tener una Entidad de clase inmutable que exponga solo los accesores con variables miembro protegidas, luego cree una Entidad Mutable que la extienda y agregue definidores. Tu versión lo impide.
  2. El uso de getters y setters se adhiere a la convención de JavaBeans. Si desea utilizar su clase como un bean en tecnologías basadas en propiedades, como JSTL o EL, debe exponer a los captadores públicos.
  3. Si alguna vez desea cambiar la implementación para derivar los valores o buscarlos en la base de datos, tendrá que refactorizar el código del cliente. Un enfoque de acceso / mutador le permite cambiar solo la implementación.
  4. Menos asombro: cuando veo variables de instancia pública, busco inmediatamente quién puede estar mutándola y me preocupa que esté abriendo la caja de pandora porque se perdió la encapsulación. enlace

Dicho esto, tu versión es definitivamente más concisa. Si se tratara de una clase especializada que solo se usa dentro de un paquete específico (tal vez el alcance del paquete sea una buena idea aquí), entonces puedo considerar esto como una sola vez. Pero no expondría grandes API como esta.

    
respondido por el Brandon 18.03.2013 - 02:57
23

Deshazte también de los que consiguen / de los que ponen, ¡y estás bien!

Este es un tema muy controvertido entre los programadores de Java.

De todos modos, hay dos situaciones en las que utilizo variables públicas (!) de getters / setters:

  1. final pública Para mí, esto indica que "soy inmutable" mucho mejor que solo un captador. La mayoría de los IDE indicarán el modificador final con una 'F' durante la finalización automática. A diferencia de getters / setters, donde tienes que buscar la ausencia de un setXXX.
  2. público no final Me encanta esto para las clases de datos. Acabo de exponer públicamente todos los campos. No getters, setters, constructores. No nada. Menos que un pojo. Para mí, esto indica de inmediato "mira, soy tonto. Tengo datos, eso es todo. Es TU trabajo poner los datos correctos dentro de mí". Gson / JAXB / etc. manejar estas clases bien Son una dicha para escribir. No hay duda sobre su propósito o capacidades. Y lo más importante: sabes que no hay efectos secundarios cuando cambias una variable. En mi humilde opinión, esto resulta en modelos de datos muy concisos con pocas ambigüedades, mientras que los captadores y los establecedores tienen este gran problema donde a veces la magia ocurre dentro de ellos.
respondido por el kritzikratzi 05.11.2014 - 19:17
9

En palabras sencillas:

  • Viola la encapsulación para guardar algunas líneas de código. Ese derrota el propósito de OOD.
  • El código del cliente se acoplará duro a los nombres de los miembros de su clase. El acoplamiento es malo. Todo el propósito de OOD está impidiendo el acoplamiento.
  • También estás muy seguro de que tu clase nunca tendrá que ser mutable. Las cosas cambian. El cambio es lo único que es constante.
respondido por el Tulains Córdova 28.05.2013 - 16:31
6

Una posible desventaja que puedo ver de repente es que estás atado a la representación interna de los datos en la clase. Probablemente esto no sea un gran problema, pero si usa los configuradores y decide que foo y bar se devolverán de alguna otra clase definida en otro lugar, no será necesario que cambien las clases que consumen MyObject. Solo deberías tocar MyObject. Sin embargo, si usas los valores desnudos, entonces deberías tocar en todos los lugares que utilicé MyObject.

    
respondido por el ipaul 18.03.2013 - 02:38

Lea otras preguntas en las etiquetas