How to use an interface with polymorphic parameters

3

I have a question about interfaces and their use, first I tell them about my problem

  • I have to build a system in which I have actions from 1 to 10, each action has individual properties, that is they are different objects
  • Here is an example with two pieces of particular actions (these objects are what I want to pass as parameters but in a generic way)

    public class AccionUno{
        private BigInteger idAccionUno;
        private Date fechaDeElaboracion;
        private String observaciones;
        private String necesidadesDeInformacion;
        private String guiaAsignada;
        //getters y setters
    }
    
    public class AccionDos{
       private BigInteger idAccionDos;
       private List<String> hechos;    
       private String descripcion
       //getters y setters
    }
    
  • Each action has a common behavior, which is to register, consult, delete, edit and validate, for which I would like to have a common interface for all actions
  • The only thing that changes is the type of parameter that enters the interface and in the case of consulting the return type also changes, in the interface I put a generic object called Action that I want to be the abstraction of all the actions
  • Here is an example of the interface and the problem lies in how to abstract a parameter of a generic type that represents all my actions

    public interface Accionable{
        public void registrarAccion(Accion accion);
        public void borrarAccion(Accion accion);
        public void editarAccion(Accion accion);
        public Accion consultarAccion(Accion accion);
    }
    

    And I would like to implement them in the following way

    public class AccionUnoImplementacion implements Accionable{
        public void registrarAccion(Accion accion){
           //Registrar accion uno
        }
        public void borrarAccion(Accion accion){
           //Borrar accion uno
        }
        public void editarAccion(Accion accion){
           //Editar accion uno
        }
        public Accion consultarAccion(Accion accion){
           //Consultar accion uno
        }
    }
    
    public class AccionDosImplementacion implements Accionable{
        public void registrarAccion(Accion accion){
           //Registrar accion dos
        }
        public void borrarAccion(Accion accion){
           //Borrar accion dos
        }
        public void editarAccion(Accion accion){
           //Editar accion dos
        }
        public Accion consultarAccion(Accion accion){
           //Consultar accion dos
        }
    }
    

    I tried to do it by overwriting the specific parameters for example

    public void registrarAccion(AccionUno accion);
    public void registrarAccion(AccionDos accion);
    

    But the problem with that is that already to make it common I have to break the principle of segregation of interfaces since each client that occupies this interface must implement the n methods even if you only need one

    Also try generic with this link

    The justification for the solution I'm looking for is to comply with the open / close principle because if it could be achieved, I would not care how many actions are added, everything specific to each implementation would be well separated from the abstraction of what a action can do

    Having said the above, I would like to know if there is any way to:

  • Make a solution like the one I describe
  • How can I achieve polymorphism through the parameters knowing that they are not equal
  • EDIT According to what you mention in the comments, I came to this solution, so I do not know what they think or if they have some kind of failure or some improvement, could something similar with interfaces be achieved? as the Duck typing of Ruby

    A Parent Class called Action, NOTESE NOT ONLY GET AND SET, CLASSES CONTAIN ENCAPSULATION LOGIC FOR EACH ONE

    public class Accion {
    
    private int idAccion;
    private String observaciones;
    
        //getters y setters
    
    /*
    Inicio Logica de encapsulación de esta clase
     */
    private boolean sonObservacionesNulas() {
        if (observaciones != null) {
            return sonObservacionesVacias();
        }
        return true;
    }
    
    private boolean sonObservacionesVacias() {
        return observaciones.trim().isEmpty();
    }
    /*
    Fin Logica de encapsulacion de esta clase
     */
    
    }
    

    A daughter class called AccionUno that extends Action

    public class AccionUno extends Accion {
    
    private Set<String> necesidades;
    
    //getters y setters
    
    /*
    Inicio Logica de encapsulacion de esta clase
     */
    public boolean sonNecesidadesValidas() {
        return sonNecesidadesNulas();
    }
    
    private boolean sonNecesidadesNulas() {
        if (necesidades != null) {
            return sonNecesidadesVacias();
        }
        return true;
    }
    
    private boolean sonNecesidadesVacias() {
        return necesidades.isEmpty();
    }
    /*
    Fin Logica de encapsulacion de esta clase
     */
    
    }
    

    A daughter class called AccionDos that extends Action

    public class AccionDos extends Accion {
    
    private Integer numeroDePersonasBeneficiadas;
    private String hechos;
    
    //getters y setters
    
    /*
    Inicio Logica de encapsulacion de esta clase
     */
    public boolean sonHechosValidas() {
        return sonHechosNulos();
    }
    
    private boolean sonHechosNulos() {
        if (hechos != null) {
            return sonHechosVacias();
        }
        return true;
    }
    
    private boolean sonHechosVacias() {
        return hechos.trim().isEmpty();
    }
    /*
    Fin Logica de encapsulacion de esta clase
     */
    
    }
    

    A generic interface that receives the parent class Action as a parameter

    public interface Accionable<T extends Accion> {
    
    public void registrarAccion(T accion);
    
    public Accion consultatAccion(T accion);
    
    public void validarAccion(T accion);
    }
    

    An implementation class corresponding to the ActionDos

    public class AccionDosImplementacion implements Accionable<AccionDos> {
    
    @Override
    public void registrarAccion(AccionDos accion) {
        System.out.println("#################################");
        System.out.println("Logica especifica para registrar una accion DOS en bd");
        accion.setIdAccion(1);
        accion.setNumeroDePersonasBeneficiadas(2);
        if (accion.getNumeroDePersonasBeneficiadas() >= 2) {
            System.out.println("Haz esto");
        } else {
            System.out.println("Esto otro");
        }
        accion.setHechos("hechos");
        accion.setObservaciones("observaciones");
        System.out.println("Registrar accion en tabla especifica de accion DOS");
    }
    
    @Override
    public Accion consultatAccion(AccionDos accion) {
        System.out.println("Buscar en base de datos accionDos en particular");
        return accion;
    }
    
    @Override
    public void validarAccion(AccionDos accion) {
        System.out.println("Buscar en base de datos accionDOS en particular para validar");
        System.out.println("Validar accion");
        System.out.println("#################################");
    }
    
    }
    

    An implementation class corresponding to the Action One

    public class AccionUnoImplementacion implements Accionable<AccionUno> {
    
    @Override
    public void registrarAccion(AccionUno accion) {
        System.out.println("#################################");
        System.out.println("Logica especifica para registrar una accion uno en bd");
        accion.setIdAccion(1);
        Set<String> necesidades = new HashSet<>();
        necesidades.add("necesidadUno");
        necesidades.add("necesidadDos");
        accion.setNecesidades(necesidades);
        accion.setObservaciones("observaciones");
        System.out.println("Registrar accion en tabla especifica de accion uno");
    }
    
    @Override
    public Accion consultatAccion(AccionUno accion) {
        System.out.println("Buscar en base de datos accion en particular");
        return accion;
    }
    
    @Override
    public void validarAccion(AccionUno accion) {
        System.out.println("Buscar en base de datos accion en particular para validar");
        System.out.println("Validar accion");
        System.out.println("#################################");
    }
    
    }
    

    Customer

    public class BeanAccionN {
    
    public static void main(String[] args) {
        //Empiezan comportamiento polimorfico con AccionUno
        Accionable accionable = new AccionUnoImplementacion();
        Accion accion = new AccionUno();
        registrar(accion, accionable);
        consultar(accion, accionable);
        validar(accion, accionable);
    
        //Empiezan comportamiento polimorfico con AccionDos
        accionable = new AccionDosImplementacion();
        accion = new AccionDos();
        registrar(accion, accionable);
        consultar(accion, accionable);
        validar(accion, accionable);
    
    }
    
    private static void registrar(Accion accion, Accionable accionable) {
        accionable.registrarAccion(accion);
    }
    
    private static void validar(Accion accion, Accionable accionable) {
        accionable.validarAccion(accion);
    }
    
    private static void consultar(Accion accion, Accionable accionable) {
        accionable.consultatAccion(accion);
    }
    
    }
    
        
    asked by jam 09.12.2016 в 23:30
    source

    1 answer

    2

    What you have to do is a parent class of all the actions that the Accionable interface will use. This parent class must have the name Accion to keep your signature.

    All other Accion* classes must extend it:

    public class AccionUno extends Accion {
        //Código de esta clase
    }
    public class AccionDos extends Accion {
        //Código de esta otra clase
    }
    

    So your services will implement the Accionable interface with the method signature that you have described for all your different classes that inherit from Accion :

    public class AccionUnoService implements Accionable{
    
        public void registrarAccion(Accion accion){
            //Resto de código
        }
    }
    
    public class AccionDosService implements Accionable{
    
        public void registrarAccion(Accion accion){
            //Resto de código
        }
    }
    
        
    answered by 10.12.2016 / 09:44
    source