Donde trabajo veo muchas clases que hacen cosas como esta:
public class ClassThatCallsItsOwnGettersAndSetters {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
setField("value");
//do stuff
String localField = getField();
//do stuff with "localField"
}
}
Si escribiera esto desde cero, habría escrito lo methodWithLogic()
siguiente en su lugar:
public class ClassThatUsesItsOwnFields {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
field = "value";
//do stuff
//do stuff with "field"
}
}
Siento que cuando la clase llama a sus propios captadores y establecedores, hace que el código sea más difícil de leer. Para mí, casi implica que está ocurriendo una lógica compleja en esa llamada al método, aunque en nuestro caso casi nunca ocurre. Cuando estoy depurando un código desconocido, ¿quién puede decir que el error no es un efecto secundario en ese método? En otras palabras, me hace hacer muchos viajes secundarios en el viaje de entender el código.
¿Hay beneficios para el primer método? ¿Es el primer método realmente mejor?
java
object-oriented
programming-practices
Daniel Kaplan
fuente
fuente
Respuestas:
No diré cuál es mejor o peor, porque eso depende en parte de su situación (en mi opinión). Pero considere que sus captadores y establecedores pueden cambiar la implementación más adelante, y omitirlos omitiría esa lógica.
Por ejemplo, ¿qué sucede si agrega una bandera "sucia" a algunos campos de configuración más adelante? Al llamar a sus configuradores en su código interno, establecerá la bandera sucia sin cambiar ningún otro código. En muchas situaciones esto sería algo bueno.
fuente
setField()
desde el principio, acaba de introducir un error.Llamar al setter directamente no es, en sí mismo, un problema. La pregunta realmente debería ser: ¿Por qué nuestro código tiene setters en todas partes?
Las clases mutables son un juego peligroso, particularmente donde la clase misma maneja su propio estado. Considere cuántos de esos setters realmente necesitan existir. ¿Cuántos podrían establecerse en el constructor y luego quedar encapsulados completamente por la clase misma?
Si el campo debe ser configurable externamente, pregúntese si el método con lógica debería estar allí. ¿Es su clase en sí misma solo una clase de datos / estado? ¿Esta clase tiene más de una responsabilidad?
No me malinterpreten, habrá casos en que esto está bien. No estoy diciendo que debas eliminar completamente a los setters en las clases con lógica. Pero estas deberían ser la excepción, no la regla. Y, en esos pocos casos, debería ser obvio a qué acceder directamente.
fuente
Sí, los métodos de su clase deberían llamar a los captadores y establecedores. El objetivo de escribir getters y setters es la prueba futura. Puede convertir cada propiedad en un campo y exponer directamente los datos a los usuarios de la clase. La razón por la que crea los captadores y establecedores no es necesariamente porque haya una lógica compleja ahora, sino para que la interfaz no se rompa en el futuro si tiene que agregarla.
fuente
someField=newValue; refresh();
Si el método permite establecer múltiples campos, llamar a los establecedores para escribir esos campos causaría operaciones redundantes de "actualización". Escribir todos los campos y luego llamarrefresh()
una vez puede generar una operación más eficiente y de aspecto más uniforme.Para responder a sus preguntas en una palabra, sí.
Tener una clase que llame a sus propios captadores y establecedores agrega extensibilidad y proporciona una mejor base para el código futuro.
Digamos que tienes algo como esto:
Llamar a los emisores por año y marca actualmente no puede agregar ninguna funcionalidad, pero ¿qué pasa si desea agregar algo como la validación de entrada a los configuradores?
fuente
Una cosa que no se ha mencionado es que getter y setter (como todos los métodos) son virtuales en Java. Esto agrega otra característica para usarlos siempre en su código. Otro usuario podría extender su clase, sobrescribiendo sus captadores y establecedores. Su clase base estaría usando los datos de la subclase en lugar de los suyos. En un lenguaje donde marca explícitamente funciones virtuales, esto es mucho más útil ya que puede predecir y declarar con qué funciones se puede hacer esto. En Java, esto es algo que siempre debería tener en cuenta. Si es un comportamiento deseado, usarlos en su código es algo bueno, de lo contrario, no tanto.
fuente
Si está tratando de lograr algo que proporciona la interfaz pública, utilice los captadores / establecedores.
Sin embargo, como propietario / desarrollador de la clase, se le permite acceder a las secciones privadas de su código (desde dentro de la clase, por supuesto), pero también es responsable de mitigar los peligros.
Entonces, tal vez tenga un getter que itera sobre alguna lista interna, y desea obtener el valor actual sin incrementar el iterador. En este caso, use la variable privada.
fuente
Si. Los captadores y los establecedores representan el estado, así que cambie esta pregunta: ¿desea tener en cuenta varias formas de cambiar el estado de un objeto de la misma manera a menos que sea necesario?
Cuantas menos cosas tenga que seguir, mejor; es por eso que los objetos inmutables son más fáciles de manejar.
Considere, no hay nada que le impida tener tanto un campo público como un captador / setter público, pero ¿qué ganaría?
En ocasiones puede ser deseable o incluso necesario acceder directamente al campo por una o más razones, no debe evitar eso si sucede. Pero realmente solo debe hacerlo si hay un beneficio definido al hacerlo.
fuente
Ambos métodos tienen sus casos de uso. Como public setter mantiene el valor del campo (y / o los valores enlazados) consistentes, debe usar setter cuando la lógica de su método no interfiere con esta lógica de coherencia. Si acaba de configurar su "propiedad", use setter. Por otro lado, hay situaciones en las que necesita acceso directo a algunos campos, por ejemplo, operaciones masivas con setter pesado u operaciones en las que el concepto de setter es demasiado simple.
Es su responsabilidad mantener las cosas consistentes. Setter hace esto por definición, pero no puede cubrir casos complejos.
fuente
Yo diría que no..
Si sus captadores / establecedores solo obtienen y configuran (sin inicialización diferida, sin controles, etc.), entonces simplemente use sus variables. Si en el futuro cambias tus captadores / setters, puedes cambiar tu
methodWithLogic()
(porque es tu clase la que está cambiando) y puedes llamar a un getter / setter en lugar de una asignación directa. Puede documentar esta llamada para el getter / setter (ya que será extraño llamar a un getter / setter cuando el resto del código de su clase está utilizando directamente la variable).La JVM incorporará llamadas frecuentes a captadores / establecedores. Entonces, nunca es un problema de rendimiento. La ganancia de usar variables es la legibilidad y en mi humilde opinión, iría por ello.
Espero que esto ayude..
fuente