as exteneder a generic class in java

-1

I want to have a class in which I can indicate which class it extends. Something like

public class ComunAux extends T {
    private MyObject obj
    [...]
}

The opposite is not valid for me: that a class extends ComunAux and thus have that MyObject field

It could also be worth to me that the ComunAux class has a field of type T, something like:

public class ComunAux<T> {
    private T parent;
    [... otros campos comunes ...]
 }

But in this last case, how do I create the parent instance in the ComunAux constructor?

IMPORTANT: working with Java 6 (1.6.0_45)

EDIT, before the doubts ...

In the second case, in the default constructor, without parameters, of ComunAux , you would need to initialize the attribute T parent so that it is not null, that is to say something like that (I know it's wrong): this.parent = new T() , because I'm going to use it in a Hibernate query and I can not use the constructor that I want (or so I think)

Why do I need this? I have to obtain from database, with Hibernate, a list of objects (A), between the data obtained there is an entire entity (let's call it X) that I do not want to leave in the final list, but instead I leave a String which contains the concatenation of various fields of X (with a special logic of concatenation). To solve this I create an auxiliary class with the X field and extend A so that it has all the data of A:

class Aaux extends A {
    X x;
    //get/set de x
}

With Aaux I make the query, obtaining a List<Aaux> listaAux . I go through all listaAux , setting the A.xx field from the Aaux.X that I have obtained I create a new list List<A> result :

List<A> result = new ....;
    for(Aaux itemAux: listaAux){
        itemAux.setX(concatenarX(itemAux.x);
        result.add(itemAux); 
        //aqui ya me quedo solo con los datos de A, sin X
    }
return result;

Now I have to repeat this in 3 more cases, each with a different entity: B, C and D. So I would have to create their corresponding auxiliary classes, all with the same X field but extending a different class: class Baux extends B class Caux extends C ...

My goal is to have a single auxiliary class that can tell you what your parent class is at the time you use it.

And for those who do not know how to hibernate ... I must indicate the class (class) to be returned, that is to say Aaux.class , or ComunAux<A>.class (as it has to be done)

Maybe I ask the impossible: (

Thanks for the answer and try:)

    
asked by Asius Ice Sword 05.10.2018 в 12:04
source

2 answers

2

We'll start with what you have right.

  

Maybe I ask the impossible: (

Correct.

Now we go with the rest.

  

My goal is to have a single auxiliary class that can tell you what your parent class is at the time you use it.

In programming (in general in all technical fields) you have to speak properly. The parent class is the one indicated in extends and can not be changed once compiled .

  

In the second case, in the default constructor, without parameters, of ComunAux, I would need to initialize the T parent attribute so that it is not null, ie something like this (I know it is wrong): this.parent = new T ( ),

You can not.

The generics information is available only at compile time . The generics are a trick for people not to do things like these:

List listaStrings = new ArrayList();
listaStrings.add(new Integer(5));
String miString = (String) listaStrings.get(0);

(obviously, it is much more complicated when you enter the list in twenty different sites and you have to review them all looking for the bug).

But at the level of binaries this information could not be entered without introducing incompatibilities with the binaries compiled for previous JVMs, and that in Java is not very popular, so it was decided that this information would not be included.

At the binary level, the previous code is identical to:

List<Object> listaStrings = new ArrayList<>();
listaStrings.add(new Integer(5));
String miString = (String) listaStrings.get(0);

and who would leave if I let you compile:

List<String> listaStrings = new ArrayList<>();
listaStrings.add(new Integer(5));
String miString = listaStrings.get(0);

This is called type erasure . So at runtime, you do not know what "T" is.

About what you are trying (or what I think you are trying to do, I have read it six or seven times and I still do not know) 1 , an option would be.

public interface Concatenable {
  String concatenar();
}

public class A implements Concatenable {
  protected String concatenar() { //Tu implementación de concatenar 
  }
}

And then an auxiliary class ( that does not have to extend from A, or B ) with the method that takes a List<Concatenable> and processes it.

In any case, my advice is generally to avoid "tricks" and "weird stories" just to avoid writing a couple of methods; maintainability and the principle of least surprise are much more important. Remember that inheritance means strong coupling and more maintenance difficulties, you have to use it only when it makes sense and appears naturally. It is generally recommended to use composition.

1 I said it right up, but I repeat it. Avoid the "genius".     
answered by 05.10.2018 в 19:26
0

In the generic class you must pass in the constructor an object of the same type that you defined the generic one, and as you can see you can define other properties like here I put a string called another thing.

Since you do not know which object is the one that arrived in your constructor since it is generic, the only way to obtain properties of it is with reflection, that way I receive the name of the property you want to obtain and try to read it of the generic object T with the getPropertyOfT method

import java.lang.reflect.Field;

public class Generic1<T> {

    private T obj;

    public Generic1(T obj){
        this.obj = obj;
    }

    public void classType() {
        System.out.println("El tipo de T es " + obj.getClass().getName());
    }

    public Object getPropertyOfT(String name) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
      Field field = obj.getClass().getDeclaredField(name);    
      field.setAccessible(true);
      Object value = field.get(obj);
      return value;
    }

    private String otraCosa = "hola";

    public String get_otraCosa() {
        return otraCosa;
    }

    public void set_otraCosa(String otraCosa) {
        this.otraCosa = otraCosa;
    }
}

Assuming we have any other object in this case I have this so-called Principal with a single property called value

public class Principal {

    private int valor = 5;

    public int getValor() {
        return valor;
    }

    public void setValor(int valor) {
        this.valor = valor;
    }
}

The call of the generic class would be in the following way, and so you could get properties from either the generic class or the T-type class

public class Ejemplo1 {

    public static void main(String[] args) {
        Generic1<Principal> g = new Generic1<Principal>(new Principal());
        System.out.println(g.get_otraCosa());
        try {
            System.out.println(g.getPropertyOfT("valor"));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Result:

    
answered by 05.10.2018 в 15:37