2013-06-20 2 views
3

у меня есть массив типа с именем ItinerarySegment, и этот тип имеет подклассы: WalkSegment, BusSegment и т.д.Внедрение Parcelable интерфейс на полиморфных массивов

public interface ItinerarySegment 
{ 

} 

public class WalkSegment implements ItinerarySegment 
{ 

} 

public class BusSegment implements ItinerarySegment 
{ 

} 

Какой стратегии я должен следовать при создании массива ItinerarySegment parcelable ? Основная проблема здесь заключается в том, как она будет использоваться позже при повторной конструкции массива с помощью метода createTypedArray (подготовленного методом writeTypedArray).

В котором метод createTypedArray принимает параметр поля Creator. Проблема здесь ... Где определить поле Creator? (в ItinerarySegment, WalkSegment, или BusSegment?).

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

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

}; 

Если я ItinerarySegment абстрактный класс и определить его метод Creator полевых, а затем данные последующих подклассов будут потеряны, так как ни один из их конструкторов с параметром Parcel, вместо ItinerarySegment «s конструктор будет вызван.

constructor(Parcel in); 

Если я WalkSegment определить Creator поле, то BusSegment будет иметь проблемы.

Нужны какие-либо разъяснения?

ответ

3

Для того, чтобы сделать это с помощью writeTypedArray() и createTypedArray() вам нужно будет сделать ItinerarySegment в abstract class, не является interface. ItinerarySegment необходимо будет реализовать Parcelable, и для этого необходимо будет определить CREATOR, который будет вызываться для развязывания Parcel и создания новых объектов. Производные классы также должны были бы реализовать методы writeToParcel(), describeContents() и CREATOR.

ПРИМЕЧАНИЕ: Поскольку writeTypedArray() НЕ записывает тип объекта в Parcel, вам нужно будет сделать это самостоятельно. Вот 2 варианта:

  1. writeParcel() метод каждого производного класса должны были бы написать что-то на Parcel в самом начале, что определяет его тип (а String или int значение).

  2. Метод writeParcel() каждого производного класса должен был бы позвонить super.writeToParcel(), прежде чем писать что-либо в Parcel. В методе ItinerarySegment.writeToParcel() вы можете выяснить, какой тип производного класса он и что-то записать в Parcel, который идентифицирует его тип (значение String или int).

CREATOR в ItinerarySegment бы сначала прочитать идентификатор из Parcel, а затем с помощью этого, определить, какой тип объекта для создания экземпляра. Затем он вызовет соответствующий объект CREATOR, чтобы фактически создать объект и вернуть его вызывающему.

Это в основном работает как объект завод, в котором базовый класс знает, как создавать экземпляры различных типов своих производных классов.

Недостатком всего этого является то, что абстрактный базовый класс должен был бы знать обо всех своих производных классах. Я полагаю, вы также могли бы сделать это динамически, поскольку все производные классы вызывали статический метод в базовом классе, передавая его «тип» и CREATOR, который затем будет хранить базовый класс в массиве, который будет использоваться по мере необходимости.

Все можно сделать, но довольно сложно.

В качестве альтернативы вы можете использовать writeParcelableArray() и readParcelableArray(), где имя класса каждого объекта записывается в Parcel так, что она знает, какие CREATOR звонить когда демаршаллизации.

ИМХО только время, чтобы использовать writeTypedArray() и createTypedArray() когда все объекты в массиве являются экземплярами одного и того же класса, и вы пишете больше, чем горстка из них в Parcel. В этом случае вы сохраняете накладные расходы на запись имени класса в Parcel для каждого объекта, так как вы знаете, что они все одинаковы. В этом случае вам не нужно проходить все агонии, описанные выше, потому что вы заранее знаете тип всех объектов (без полиморфных типов).

Я понимаю, что этот ответ, вероятно, более чем на год, но что это такое. Может быть, это поможет кому-то еще ;-)

+2

Я понимаю, что этот комментарий более чем на год позже :-), но да, ваш ответ полезен. Мне было интересно, как Java распаковал полиморфные посылки в правильные типы ... и теперь я понимаю, что это не так. :-(Очень жаль, но заводский подход, который вы предлагаете, должен работать. – dajames

Смежные вопросы