Si utiliza el nombre del campo, no obtiene la encapsulación. La encapsulación se aplica no solo entre clases, sino también dentro de una clase.
Si en algún momento futuro redefine el campo pero deja las firmas de la función de acceso/configuración iguales, no solo las clases externas que usan su clase no se romperán, sino que las rutinas internas de su propia clase tampoco se romperán .
Tomemos por ejemplo el código, basado libremente en el código que aparece en el marco de Apache Wicket (aunque el marco no sufre este problema, yo sólo estoy usando ilustrar):
Digamos que esto fuera la clase original:
class RadioChoice {
private String prefix;
RadioChoice(String prefix) {
this.prefix = prefix ;
setPrefix(String prefix) {
this.prefix = prefix ;
}
}
Aquí ya podemos ver un problema: la misma operación this.prefix = prefix
ocurre en lugares de remolque. Tiene la intención de hacer exactamente lo mismo, pero dado que ocurre en dos lugares, esa "misma cosa" puede dividirse en dos cosas diferentes. (Compare esto con la normalización de la base de datos, una práctica diseñada para evitar exactamente eso.)
Ahora, Apache Wicket tiene un concepto de grabación de cambios en la forma en que procesa las páginas web, para que esos cambios puedan deshacerse. Lo hace almacenando una lista de objetos "deshacer". prefijo de un RadioChoice es una de esas cosas que se pueden deshacer, por lo que el colocador 'prefijo' debe registrar el cambio:
class RadioChoice {
private String prefix;
RadioChoice(String prefix) {
this.prefix = prefix ;
setPrefix(String prefix) {
// save the old prefix
this.getPage().addChange(new PrefixChange(this.prefix));
// set the new one
this.prefix = prefix ;
}
}
Ahora mira lo que pasa: porque el constructor establece el prefijo directamente, ningún cambio es salvado por el ctor. Si hubiéramos usado el colocador, el ctor automáticamente "haría lo correcto" después de una refactorización. En su lugar, tenemos que refactorizar el setter y el ctor.
Por supuesto, nuestro código sigue siendo inferior a la óptima, en realidad, debería ser esta:
setPrefix(String prefix) {
// save the old prefix
this.getPage().addChange(new PrefixChange(this.getPrefix()));
// set the new one
this.prefix = prefix ;
}
}
Scott Meyers tenía una serie de artículos sobre este, donde abogó que (en C++, que tiene funciones libres) una clase exponer solo funciones primitivas (funciones primitivas: funciones no posibles excepto por la clase iteslf) y que todas las funciones que podrían estar compuestas de funciones primitivas se hagan funciones libres. Esto lo convierte en una interfaz más delgada, una interfaz más estable.
De la misma manera, en la medida en que puede considerar que las funciones de la clase dependen solo de su interfaz primitiva, tendrá más flexibilidad; en particular, esas funciones son candidatas para ser retiradas de la clase. De manera más general, usar setters y getters lo aísla de los cambios.
Sí, es un gran beneficio de C#. – Randolpho
¿De qué estás hablando para aquellos de nosotros que no conocemos estas cosas de javabeaner? –
No debe seguir las convenciones simplemente porque "todo el mundo parece usarlas", especialmente si no puede justificarlo usted mismo. La convención no implica ni prueba que sea una buena idea. ¡Cuestión! :) – JoshJordan