2012-09-26 16 views
8

Questa è una domanda generale di JAVA. In androide, v'è un'interfaccia Parcelable:Classe generica con problema di accesso con vincoli

Questo è un esempio all'interno del official documentation:

public class MyParcelable implements Parcelable { 
    private int mData; 

    public int describeContents() { 
     return 0; 
    } 

    public void writeToParcel(Parcel out, int flags) { 
     out.writeInt(mData); 
    } 

    public static final Parcelable.Creator<MyParcelable> CREATOR 
      = new Parcelable.Creator<MyParcelable>() { 
     public MyParcelable createFromParcel(Parcel in) { 
      return new MyParcelable(in); 
     } 

     public MyParcelable[] newArray(int size) { 
      return new MyParcelable[size]; 
     } 
    }; 

    private MyParcelable(Parcel in) { 
     mData = in.readInt(); 
    } 
} 

Siamo tenuti per implementare le funzioni describeContents() 2 e writeToParcel.

(problema) Oltre a loro, si devono inoltre implementare l'interfaccia Parcelable.Creator<T> come un campo statico chiamato CREATOR.

Tutto è davvero semplice. Ora voglio creare una classe generica che ha un Parcelable Classe Tipo:

public class ShushContainer<T extends Parcelable> implements Parcelable 

sono in grado di implementare Parcelable. Posso chiamare la funzione di . Tuttavia, non riesco ad accedere al campo CREATORE statico.

public class ShushContainer<T extends Parcelable> implements Parcelable { 
    Vector<T> items; 
    String someField; 

    @Override 
    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     dest.writeString(someField); 
     dest.writeInt(items.size()); 
     for(int i=0;i<items.size();i++) 
      items.get(i).writeToParcel(dest, flags); 
    } 

    public ShushContainer(Parcel in) { 
     someField = in.readString(); 
     int size = in.readInt(); 
     for(int i=0;i<size;i++) 
      //this does not work 
      items.add(T.CREATOR.createFromParcel(in)); 
    } 

    public static final Parcelable.Creator<ShushContainer> CREATOR = new Parcelable.Creator<ShushContainer>() { 
     public ShushContainer createFromParcel(Parcel in) { 
      return new ShushContainer(in); 
     } 

     public ShushContainer[] newArray(int size) { 
      return new ShushContainer[size]; 
     } 
    }; 
} 

risposta

1

Invece di <T extends Parcelable> è necessario <T extends ShushContainer<T> & Parcelable> questo modo si specifica che T è ShushContainer modo da poter accedere è metodi e variabili.

public class ShushContainer<T extends ShushContainer<T> & Parcelable> 
implements Parcelable 

Ecco l'esempio utilizzando Serializable

class Sample<T extends Sample<T> & Serializable> implements Serializable { 

    public static int CONST = 0; 

    public void foo() 
    { 
    T.CONST = 5; 
    } 
} 

Aggiornamento

Se ho capito bene threre è un'altra classe che implementa Parcelable che ha CREATOR Si sta tentando polimorfismo dinamico per le variabili statiche che non è possibile.

esempio di esempio per mostrare come fallisce

public class Base { 
    public static int count = 10; 
} 

public class Child extends Base { 
    public static int count = 20; 
} 


class Sample<T extends Base> { 
    T t = null; 
    public void printCount() { 
     System.out.println(T.count); 
    } 
    public Sample(T t) { 
     this.t = t; 
    } 

    public static void main(String[] args) { 
     Sample<Child> sample = new Sample<Child>(new Child()); 
     Sample<Base> sample1 = new Sample<Base>(new Base()); 
     sample.printCount();//Child value printed as 10 
     sample1.printCount();//Same for parent value printed as 10 
    } 

} 

Questo programma non è riuscito perché i campi statici sono tenuti a classe piuttosto che istanza in modo ci sono due separati count uno per Base e uno per Child se si accede valore Base quindi sarà sempre 10.

È possibile utilizzare la riflessione per verificare se il campo CREATOR è presente e accedervi. Che cosa non sarà possibile senza oggetto o oggetto di classe.

o si può fare qualcosa di simile di seguito utilizzando TypeToken

class Sample<T extends Serializable> implements Serializable { 

    public int abc = 0; 
    public void foo() { 
    } 
    public static void main(String[] args) throws SecurityException, NoSuchFieldException { 
     TypeToken<Sample<Integer>> token = new TypeToken<Sample<Integer>>() { 
     }; 
     Class<?> t = token.getRawType(); 
     Field field = t.getDeclaredField("abc"); 
     field.setAccessible(true); 
     System.out.println(field.getName()); 

    } 
} 
+0

T è un'altra classe che implementa Parcelable. –

+0

Quindi come può quella classe avere 'CREATOR' perché è definita in ShushContainer. Questa variabile appartiene solo a questa classe. Semplicemente usalo perché hai bisogno di T.CREATOR Usa semplicemente CREATOR –

+0

Nopes ShushContainer implementa Parcelable e ha il suo CREATORE. T implementa anche Parcelable e ha il suo CREATORE. È questo CREATORE a cui non riesco ad accedere. –

0

Ciò non rispondere alla tua domanda su come accedere alla proprietà CREATORE statica, tuttavia non hanno bisogno di accedere a questa proprietà implementare Parcelable. Vedi sotto per esempio:

public class TestModel<T extends Parcelable> implements Parcelable { 

private List<T> items; 
private String someField; 

public List<T> items() { 
    return items; 
} 

public void setItems(List<T> newValue) { 
    items = newValue; 
} 

public String someField() { 
    return someField; 
} 

public void setSomeField(String newValue) { 
    someField = newValue; 
} 

//region: Parcelable implementation 

public TestModel(Parcel in) { 
    someField = in.readString(); 

    int size = in.readInt(); 
    if (size == 0) { 
     items = null; 
    } 

    else { 

     Class<?> type = (Class<?>) in.readSerializable(); 

     items = new ArrayList<>(size); 
     in.readList(items, type.getClassLoader()); 
    } 
} 

@Override 
public int describeContents() { 
    return 0; 
} 

@Override 
public void writeToParcel(Parcel dest, int flags) { 
    dest.writeString(someField); 

    if (items == null || items.size() == 0) 
     dest.writeInt(0); 

    else { 
     dest.writeInt(items.size()); 

     final Class<?> objectsType = items.get(0).getClass(); 
     dest.writeSerializable(objectsType); 

     dest.writeList(items); 
    } 

    dest.writeInt(items.size()); 
    for(int i=0;i<items.size();i++) 
     items.get(i).writeToParcel(dest, flags); 
} 

public static final Parcelable.Creator<TestModel> CREATOR = new Parcelable.Creator<TestModel>() { 
    public TestModel createFromParcel(Parcel in) { 
     return new TestModel(in); 
    } 

    public TestModel[] newArray(int size) { 
     return new TestModel[size]; 
    } 
}; 

//endregion 
} 
Problemi correlati