Una de las dudas más habituales
cuando trabajamos con Programación Orientada a Objeto es como se manejan
los métodos set/get de una clase. En ocasiones pueden parecer
superfluos pero siempre se acaban implementando.
Encapsulación y reglas de negocio
Normalmente la encapsulación sirve para tener un mayor control sobre el acceso a cada una de las propiedades de un objeto determinado. Por ejemplo en la clase Cliente se valida el CIF antes de asignarlo a través de un método set.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | package es.genbetadev;
public class Cliente {
private String cif;
private String nombre;
private String calle;
private int codigoPostal;
public Cliente(String cif, String nombre, String calle, int codigoPostal) {
super ();
this .cif = cif;
this .nombre = nombre;
this .calle = calle;
this .codigoPostal = codigoPostal;
}
public String getCif() {
return cif;
}
public void setCif(String cif) {
if (Utilidades.formato(cif)) {
this .cif = cif;
} else {
throw new RuntimeException( "el formato no es adecuado" );
}
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this .nombre = nombre;
}
public String getCalle() {
return calle;
}
public void setCalle(String calle) {
this .calle = calle;
}
public int getCodigoPostal() {
return codigoPostal;
}
public void setCodigoPostal( int codigoPostal) {
this .codigoPostal = codigoPostal;
}
}
|
El concepto de delegación y la encapsulación
Sin embargo no es para lo único que se usan los métodos set/get. Si en el modelo apareciera la clase Edificio existiría un problema.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | package es.genbetadev;
public class Edificio {
private int id;
private String calle;
private int codigoPostal;
public Edificio( int id, String calle, int codigoPostal) {
super ();
this .id = id;
this .calle = calle;
this .codigoPostal = codigoPostal;
}
public int getId() {
return id;
}
public void setId( int id) {
this .id = id;
}
public String getCalle() {
return calle;
}
public void setCalle(String calle) {
this .calle = calle;
}
public int getCodigoPostal() {
return codigoPostal;
}
public void setCodigoPostal( int codigoPostal) {
this .codigoPostal = codigoPostal;
}
}
|
Ambas clases tienen el concepto de Dirección asociado a ellas y hay un problema de repetición de código.
Por lo tanto se creará una nueva clase "Dirección" para almacenar esa lógica de negocio.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | package es.genbetadev2;
public class Direccion {
private String calle;
private int codigoPostal;
public String getCalle() {
return calle;
}
public void setCalle(String calle) {
this .calle = calle;
}
public int getCodigoPostal() {
return codigoPostal;
}
public void setCodigoPostal( int codigoPostal) {
this .codigoPostal = codigoPostal;
}
public Direccion(String calle, int codigoPostal) {
super ();
this .calle = calle;
this .codigoPostal = codigoPostal;
}
}
|
Tanto la clase Cliente como la clase Edificio delegarán en la clase Dirección a la hora de gestionar esa información.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | package es.genbetadev1;
public class Cliente {
private String cif;
private String nombre;
private Direccion direccion;
public Cliente(String cif, String nombre, Direccion direccion) {
super ();
this .cif = cif;
this .nombre = nombre;
this .direccion = direccion;
}
public Direccion getDireccion() {
return direccion;
}
public void setDireccion(Direccion direccion) {
this .direccion = direccion;
}
public String getCif() {
return cif;
}
public void setCif(String cif) {
if (Utilidades.formato(cif)) {
this .cif = cif;
} else {
throw new RuntimeException( "el formato no es adecuado" );
}
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this .nombre = nombre;
}
}
|
Esto hará más complicado trabajar con las clases ya que habrá que acceder al código postal usando c.getDireccion().getCodigoPostal() ya que se ha usado composición. Para eliminar este problema se usa el patrón delegación que ayuda a encapsular la clase Dirección apoyandose en los métodos set/get.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | package es.genbetadev2;
public class Cliente {
private String cif;
private String nombre;
private Direccion direccion;
public Cliente(String cif,String nombre,String calle, int codigoPostal ) {
super ();
this .cif = cif;
this .nombre = nombre;
this .direccion = new Direccion(calle,codigoPostal);
}
public String getCalle() {
return direccion.getCalle();
}
public void setCalle(String calle) {
direccion.setCalle(calle);
}
public int getCodigoPostal() {
return direccion.getCodigoPostal();
}
public void setCodigoPostal( int codigoPostal) {
direccion.setCodigoPostal(codigoPostal);
}
public String getCif() {
return cif;
}
public void setCif(String cif) {
if (Utilidades.formato(cif)) {
this .cif = cif;
} else {
throw new RuntimeException( "el formato no es adecuado" );
}
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this .nombre = nombre;
}
}
|
De esta forma el Programador podrá volver a invocar c.getCodigoPostal() y el método devolverá la calle del objeto Cliente. Se habrán usado los métodos get/set para encapsular una clase. Si existiera un programa main su código sería el siguiente.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package es.genbetadev2;
public class Principal {
public static void main(String[] args) {
Cliente c= new Cliente ( "12345678A" , "pepe" , "calle1" , 2000 );
System.out.println(c.getCodigoPostal());
}
}
|
Como se puede observar el desarrollador ni siquiera es consciente de que la clase Dirección existe en el modelo.
Se ha usado la encapsulación para ocultar clases y la delegación para
mantener el modelo sencillo de cara a los desarrolladores. Muchos IDEs
soportan el concepto de delegación a través de sus opciones de
refactoring. Eclipse es uno de ellos :