2012-05-02 24 views
65

Duplicar posible:
Why use getters and setters?¿Cuál es el punto de los getters y setters?

He leído libros sobre Java, diciendo que es buena para crear incubadoras y captadores de variables tales como x y y. Por ejemplo:

public int getX(){ 
    return x; 
} 

public void setX(int x){ 
    this.x = x; 
} 

Pero cuál es la diferencia entre eso y

...(shape.x)... // basically getX() 

y

shape.x = 90; // basically setX() 

Si setters y getters son mejores, ¿podría explicarme qué problemas prácticos surgiría ?

+2

ver esto http://stackoverflow.com/a/1568230/985143 –

+1

duplicado exacto @ZazGmy –

+4

La verdad es que los [gs] etters son una gran carga y realmente debe sopesar el costo y el beneficio en cada caso. ¡Hay ejemplos donde los campos públicos (especialmente si puedes hacerlos definitivos!) Son la manera correcta. –

Respuesta

71

razones múltiples:

  • Si permite el acceso campo como

    shape.x = 90

entonces no se puede añadir ninguna lógica en el futuro para validar los datos .

decir si x no puede ser inferior a 100 que no puede hacerlo, sin embargo, si usted tenía los emisores como

public void setShapeValue(int shapeValue){ 
    if(shapeValue < 100){ 
    //do something here like throw exception. 
    } 
} 
  • No se puede agregar algo así como copia de la lógica de escritura (ver CopyOnWriteArrayList)
  • Otra razón es para acceder a campos fuera de tu clase, deberás marcarlos como públicos, protegidos o predeterminados, y así perderás el control. Cuando los datos son muy internos a la clase que rompe Encapsulation y en general a la metodología OOPS.

A pesar de las constantes como

public final String SOMETHING = "SOMETHING"; 

va a permitir el acceso de campo, ya que no se pueden cambiar, por ejemplo, la variable que va a colocarlos con getters, emisores.

  • Otro escenario es cuando usted quiere que su clase sea inmutable, si se permite el acceso de campo, entonces está violando la inmutabilidad de su clase ya que los valores se pueden cambiar. Pero si diseñas cuidadosamente tu clase con getters y sin setters, mantienes intacta la inmutabilidad.

Aunque en tales casos debe tener cuidado con el método getter para asegurarse de no dar referencias de objetos (en caso de que su clase tenga un objeto como instancias).

Podemos usar las variables privadas en cualquier paquete usando getters y setters.

+0

"copiar al escribir" no tiene sentido el 99% de las veces de todos modos. Imagine "copiar al escribir" en 'shape.x' ... – Pacerier

+1

¿No debería uno poder refactorizar a los miembros del campo público en privado con getters/setters si alguna vez surge la necesidad de alguna otra lógica dentro de getters/setters? Setters y getters parece ser una optimización prematura de literalmente "escribir líneas de código más tarde". La única razón para escribir getters/setters desde el principio es si desea que esta interfaz sea pública para algún código sobre el que no tenga control y no quiera romper la compatibilidad con versiones anteriores. – andrybak

+0

Falso. Puede validar datos con una instrucción if en el código principal o una función de validación. – DarmaniLink

7

El uso de las funciones getter y setter permite restricciones y encapsulamiento. Digamos que x es el radio. shape.x = -10 no tendría mucho sentido. Además, si alguien intenta establecer un valor ilegal, puede imprimir un error, establecer un valor predeterminado o no hacer nada.

Es una buena práctica hacer que las variables miembro sean privadas para que no puedan ser modificadas directamente por programas que las usen.

Mutator functions
Encapsulation

1

Hay un montón de razones. Aquí hay solo algunos.

  1. Los accesores, especialmente los buscadores, a menudo aparecen en las interfaces. No puede estipular una variable miembro en una interfaz.
  2. Una vez que exponga esta variable de miembro, no puede cambiar de opinión acerca de cómo se implementa. Por ejemplo, si luego ve la necesidad de cambiar a un patrón como la agregación, donde quiere que la propiedad "x" provenga realmente de algún objeto anidado, terminará teniendo que copiar ese valor e intentar mantenerlo sincronizado. No está bien.
  3. La mayoría de las veces usted está mucho mejor que no exponiendo el colocador. No puedes hacer eso con campos públicos como x.
0

Yo diría que ni los getters/setters ni los miembros del público son buenos diseño orientado a objetos. Ambos rompen la Encapsulación OOP al exponer datos de objetos al mundo que probablemente no deberían tener acceso a las propiedades del objeto en primer lugar.

+0

Tienes razón, este es un ejemplo de encapsulación en letras, pero no espíritu. Sin embargo, debes tener en cuenta la realidad en la que realmente solo necesitamos estructuras simples. Cuando se definieron los JavaBeans, una parte integral del diseño fue 'PropertyChangeListener's: JavaBeans se diseñó principalmente con Swing en mente. Si desea cambios de propiedad observables, no puede escapar getters y setters. –

0

Esto se hace aplicando el principio encapsulation de OOP.

Mecanismo de lenguaje para restringir el acceso a algunos de los componentes del objeto.

Esto significa que debe definir la visibilidad de los atributos y métodos de sus clases. Hay 3 visibilidades comunes:

  • Privado: Solo la clase puede ver y usar los atributos/métodos.
  • Protegido: Solo la clase y sus hijos pueden ver y usar los atributos/métodos.
  • Público: cada clase puede ver y usar los atributos/métodos.

Cuando se declara atributos particulares/protegidas, se le anima a crear métodos para obtener el valor (obtener) y cambie el valor (conjunto). Un ejemplo de visibilidad es la clase [ArrayList][2]: tiene una propiedad size para conocer el tamaño real de la matriz interna.Sólo el mosto clase cambia su valor, por lo que el código es algo así como

public class ArrayList<E> { 
    private int size; 
    private Object[] array; 
    public getSize() { 
     return this.size; 
    } 
    public void add(E element) { 
     //logic to add the element in the array... 
     this.size++; 
    } 
} 

En este ejemplo, se puede ver que el valor de tamaño se puede cambiar sólo dentro de los métodos de la clase, y se puede obtener el tamaño real de llamándolo en su código (no se mutando):

public void someMethod() { 
    List<String> ls = new ArrayList<String>(); 
    //adding values 
    ls.add("Hello"); 
    ls.add("World"); 
    for(int i = 0; i < ls.size(); i++) { 
     System.out.println(ls.get(i)); 
    } 
} 
0

captadores y definidores encapsular los campos de una clase haciéndolos accesibles sólo a través de sus métodos públicos y mantener los valores propios privado. Eso se considera un buen principio OO.

Concedido, a menudo parece un código redundante si no hace nada más que establecer o devolver un valor. Sin embargo, los setters también te permiten hacer validaciones o limpiezas de entrada. Tener eso en un solo lugar mejora la integridad de los datos para sus objetos,

1

¡Antes de entrar en la respuesta, tenemos que saber algo antes ...! "JavaBeans".
JavaBeans son clases de Java que tienen propiedades. Para nuestro propósito, piense en las propiedades como variables de instancia privadas. dado que son privados, la única forma en que se puede acceder al desde fuera de su clase es a través de 'métodos' en la clase.
Los métodos que cambian el valor de una propiedad se llaman métodos setter, y los métodos que recuperan el valor de una propiedad se llaman getter methods.

0

Porque estamos utilizando el lenguaje de programación orientado a objetos. Aquí estamos usando ocultación y encapsulación de datos. La variable no debe acceder directamente desde el mundo fuera del lado (por achiving ocultación de datos) por lo que se creará de manera privada

shape.x

no es correcto. El método getter y setter se usan para obtener y establecer el valor de x, que es la forma de lograr la encapsulación.

4

Una de las mejores razones que se me ocurren para getters y setters es la permanencia de la API de una clase. En idiomas como Python puede acceder a los miembros por su nombre y cambiarlos a métodos posteriores. Debido a que las funciones se comportan de manera diferente a los miembros en Java una vez que accede a una propiedad eso es todo. Restringir su alcance más tarde rompe al cliente.

Al proporcionar getters y setters, un programador tiene la flexibilidad de modificar los miembros y el comportamiento libremente, siempre y cuando se adhiera al contrato descrito por la API pública.

3

Digamos, hipotéticamente, que encuentra una biblioteca que hace un mejor trabajo de lo que ha estado haciendo en su propia clase (YourClass). Lo natural a hacer en este punto es hacer que YourClass sea una interfaz envoltorio para esa biblioteca. Todavía tiene un concepto de "X" que su código de cliente necesita obtener o establecer. Naturalmente, en este punto, prácticamente tiene que escribir las funciones de acceso.

Si omite usar las funciones de acceso y permite que su código de cliente acceda directamente a YourClass.x, ahora tendrá que volver a escribir todo el código de su cliente que haya tocado YourClass.x. Pero si estuvo utilizando YourClass.getX() y YourClass.setX() desde el principio, solo necesitará volver a escribir YourClass.

Uno de los conceptos clave de la programación, y especialmente la programación orientada a objetos, es ocultar los detalles de implementación para que no sean utilizados directamente por el código en otras clases o módulos. De esta forma, si alguna vez cambia los detalles de la implementación (como en el ejemplo anterior), el código del cliente no conoce la diferencia y no tiene que modificarse. Para todo lo que sabe su código de cliente, "x" podría ser una variable, o podría ser un valor que se calcula sobre la marcha.

Esto es una simplificación excesiva y no cubre todos los escenarios donde la implementación de ocultamiento es beneficiosa, pero es el ejemplo más obvio. El concepto de ocultar los detalles de la implementación está muy relacionado con OOP ahora, pero puede encontrar discusiones que se remontan décadas antes de que se idease OOP. Se remonta a uno de los conceptos centrales del desarrollo de software, que es tomar un gran problema nebuloso y dividirlo en pequeños problemas bien definidos que se pueden resolver fácilmente. Las funciones de los accesorios ayudan a mantener sus pequeñas subtareas separadas y bien definidas: cuanto menos conozcan las clases sobre las partes internas de las otras, mejor.

4

Otra buena razón para captador de usuario y setter se puede entender por el siguiente ejemplo

public class TestGetterSetter{ 
    private String name ; 


    public void setName(String name){ 
     this.name = name ; 
    } 


    public String getName(String name){ 
     return this.name ; 
    } 
} 

El punto de captadores y definidores es que sólo están destinados a ser utilizados para acceder a la Varialble privado, que son obteniendo o estableciendo De esta forma, proporciona la encapsulación y será mucho más fácil refactorizar o modificar su código más adelante.

Imagine que usa nombre en lugar de su captador. Luego, si desea agregar algo como un valor predeterminado (digamos que el nombre predeterminado es 'Invitado' si no se configuró antes), entonces tendrá que modificar tanto el captador como la función sayName.

public class TestGetterSetter{ 
    private String name ; 


    public void setName(String name){ 
     this.name = name ; 
    } 


    public String getName(String name){ 
     if (this.name == null){ 
      setName("Guest"); 
     } 
     return this.name ; 
    } 
} 

No es necesario que getters y setter comiencen con get y set; son solo funciones de miembro normales. Sin embargo, es una convención hacer eso. (Especialmente si se utiliza Java Beans)

+5

¡Los getters y setters son el peor anatema para la refactorización! Intente cambiar 30 de sus 50 propiedades JavaBean de los campos de Cadena a Fecha, por ejemplo. –

3

Originalmente, getter/setter patrón fue creado para promover el buen diseño orientado a objetos por encapsulating el funcionamiento interno de un class de su interface externa.

  • ocultar la representación interna de la propiedad

esta es la mejor respuesta de su pregunta Why use getters and setters?

6

Una gran cantidad de personas han mencionado que encapsula las características específicas de la aplicación, que para mí es la La razón más importante para usar getters y setters en una clase. Con esto, también obtendrá una gran cantidad de otros beneficios, incluida la capacidad de descartar y reemplazar la implementación por un capricho sin necesidad de tocar cada parte del código que utiliza su clase. En un proyecto pequeño, eso no es un gran beneficio, pero si su código termina siendo una biblioteca bien utilizada (interna o pública), puede ser un gran beneficio de .

Un ejemplo específico: números complejos en matemáticas. Algunos idiomas los tienen como característica de lenguaje o marco, otros no. Usaré una clase mutable como ejemplo aquí, pero podría ser tan fácilmente inmutable.

Se puede escribir un número complejo en el formulario a + bi con partes reales e imaginarias, que se presta bien a [gs]etRealPart y [gs]etImaginaryPart.

Sin embargo, en algunos casos es más fácil razonar sobre números complejos en la forma polar re^(iθ), dando [gs]etRadius (r) y [gs]etAngle (θ).

También puede exponer métodos como [gs]etComplexNumber(realPart, imaginaryPart) y [gs]etComplexNumber(radius, angle). Dependiendo de los tipos de argumento, estos pueden o no necesitar nombres diferentes, pero luego el consumidor de la clase puede usar cualquiera que se adecue a sus necesidades.

Las dos formas son intercambiables; puede convertir fácilmente de uno a otro, por lo que la forma que utiliza la clase para el almacenamiento interno es irrelevante para los consumidores de esa clase. Sin embargo, los consumidores pueden usar cualquier forma. Si elige el formulario a + bi para la representación interna, y expone que usar campos en lugar de getters y setters, no solo fuerza a los consumidores de la clase a usar ese formulario, sino que tampoco puede cambiar fácilmente de opinión y reemplazar el interno representación con re^(iθ) porque resulta más fácil de implementar en su escenario particular. Estás atrapado con la API pública que has definido, que exige que específicamente las partes reales e imaginarias se expongan usando nombres de campos específicos.

+0

Esto también se aplica a cosas como unidades de medida, o coordenadas absolutas vs. relativas. –

Cuestiones relacionadas