Java 抽象类是可包裹的

Java 抽象类是可包裹的,java,android,design-patterns,inheritance,parcelable,Java,Android,Design Patterns,Inheritance,Parcelable,基本上,我的应用程序具有以下结构: 在没有抽象类ProjectItem的情况下实现这样的结构是很简单的,但是在这种情况下,我不知道如何实现它 抽象类ProjectItem需要一个CREATOR,因为它应该是可打包的。(如 in.readTypedList(mProjectItems,ProjectItem.CREATOR);在构造函数项目中(Parcel in)) 但实际上,出于逻辑原因,CREATOR只能在其派生类中实现 那么,如何实现这种结构以保持类Projectparcelable 编辑

基本上,我的应用程序具有以下结构:

在没有抽象类
ProjectItem
的情况下实现这样的结构是很简单的,但是在这种情况下,我不知道如何实现它

抽象类
ProjectItem
需要一个
CREATOR
,因为它应该是可打包的。(如
in.readTypedList(mProjectItems,ProjectItem.CREATOR);
在构造函数项目中(Parcel in))

但实际上,出于逻辑原因,
CREATOR
只能在其派生类中实现

那么,如何实现这种结构以保持类
Project
parcelable

编辑

这就是
Project
的一个构造函数的样子:

private Project(Parcel in) {
    in.readTypedList(mProjectItems, ProjectItem.CREATOR);
}
但是正如我已经说过的,
ProjectItem
不应该实现
CREATOR

公共抽象类a实现Parcelable{
public abstract class A implements Parcelable {
    private int a;

    protected A(int a) {
        this.a = a;
    }

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

    protected A(Parcel in) {
        a = in.readInt();
    }
}

public class B extends A {
    private int b;

    public B(int a, int b) {
        super(a);
        this.b = b;
    }

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

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

    public int describeContents() {
        return 0;
    }
}
私人INTA; 受保护A(INTA){ 这个a=a; } 公共无效写入包(包出,内部标志){ 出、出、出(a); } 受保护的一个(包裹中){ a=in.readInt(); } } 公共类B扩展了A{ 私人INTB; 公共B(内部a、内部B){ 超级(a); 这个.b=b; } public static final Parcelable.Creator=新建Parcelable.Creator(){ 公共B createFromParcel(地块中){ 返回新的B(in); } 公共B[]新数组(整数大小){ 返回新的B[尺寸]; } }; 公共int描述内容(){ 返回0; } }
我的解决方案与evertvandenbruel的类似。但我使用int标识具体类,以便使用开关块。我在静态getConcreteClass(Parcel)方法中也有这个开关块

AbstractClass.java

public abstract class AbstractClass implements Parcelable {

public static final int CLASS_TYPE_ONE = 1;
public static final int CLASS_TYPE_TWO = 2;

public static final Creator<AbstractClass> CREATOR = new Creator<AbstractClass>() {
    @Override
    public AbstractClass createFromParcel(Parcel source) {

        return AbstractClass.getConcreteClass(source);
    }

    @Override
    public AbstractClass[] newArray(int size) {
        return new AbstractClass[size];
    }
};

protected String mAbstractClassString;

public AbstractClass(String abstractClassString) {
    mAbstractClassString = abstractClassString;
}

public AbstractClass(Parcel source) {
    mAbstractClassString = source.readString();
}

public static AbstractClass getConcreteClass(Parcel source) {

    switch (source.readInt()) {
        case CLASS_TYPE_ONE:
            return new ConcreteClassOne(source);
        case CLASS_TYPE_TWO:
            return new ConcreteClassTwo(source);
        default:
            return null;
    }
}

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

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

@Override
public String toString() {
    return "Parent String: " + mAbstractClassString + '\n';
}
}
concreteClass2.java

public class ConcreteClassTwo extends AbstractClass {

private String mString;
private int mInt;

public ConcreteClassTwo(String abstractClassString, String string, int anInt) {
    super(abstractClassString);
    mString = string;
    mInt = anInt;
}

public ConcreteClassTwo(Parcel source) {
    super(source);
    mString = source.readString();
    mInt = source.readInt();
}

@Override
public void writeToParcel(Parcel dest, int flags) {

    dest.writeInt(CLASS_TYPE_TWO);
    super.writeToParcel(dest, flags);
    dest.writeString(mString);
    dest.writeInt(mInt);
}

@Override
public String toString() {

    String string = super.toString();
    for (int i = 0; i < mInt; i++) {
        string = string.concat("Child String: " + mString + '\n');
    }
    return string;
}
}
公共类ConcreteClass2扩展了AbstractClass{
私有字符串mString;
私人铸币厂;
公共具体类2(字符串abstractClassString,字符串String,int-anInt){
超级(抽象类字符串);
mString=string;
薄荷=薄荷;
}
公共服务类别二(地块来源){
超级(来源);
mString=source.readString();
mInt=source.readInt();
}
@凌驾
公共无效写入包裹(包裹目的地,内部标志){
目的写入(第二类);
超级可写包裹(目的地、旗帜);
目的写入字符串(mString);
目的地记录(造币厂);
}
@凌驾
公共字符串toString(){
String=super.toString();
for(int i=0;i
选择的答案(来自evertvandenbruel的帖子)有一个bug。当只有一个子类被打包时,正确的代码必须考虑到打包,而不仅仅是一个超类对象列表

所有其他代码都应该相同,关键是您必须在所有创建者中读取类型变量(请参见下面的代码)。否则,在尝试解压子类对象时,排序将出现问题

例:

package com.example.parcelable\u example.model;
导入android.os.packet;
导入android.os.Parcelable;
公营猫科动物{
公共Cat(字符串名称){
超级(名称“Cat”);
}
公共int描述内容(){
返回0;
}
公共无效写入包裹(包裹目的地,内部标志){
dest.writeString(getType());
超级可写包裹(目的地、旗帜);
}
公共Cat(包裹来源){
超级(来源);
}
public static final Parcelable.Creator=新建Parcelable.Creator(){
公共Cat createFromParcel(地块中){
/**别忘了这个**/
type=in.readString();
返回新的Cat(in);
}
公共Cat[]新数组(整数大小){
返回新的猫[大小];
}
};
}

这个问题源于一个错误的假设


这是一段原始帖子的引文

抽象类ProjectItem需要一个创建者 可包裹的

事实上,超级类不必定义CREATOR,因为它是抽象的


下面是一个演示该方法的最小示例

/*   Super class   */

abstract class SuperClass
        implements Parcelable {

    protected SuperClass(Parcel in) {
        mSuperId = in.readLong();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(mSuperId);
    }

}



/*   Sub class   */

public class SubClass
        extends SuperClass {

    protected SubClass(Parcel in) {
        super(in);
        mSubId = in.readLong();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeLong(mSubId);
    }

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

    public static final Creator<SubClass> CREATOR = new Creator<SubClass>() {

        @Override
        public SubClass createFromParcel(Parcel in) {
            return new SubClass(in);
        }

        @Override
        public SubClass[] newArray(int size) {
            return new SubClass[size];
        }

    };

}



/*   Usage   */

class AnotherClass {

    void aMethod() {
        Bundle args = new Bundle();
        args.putParcelable("EXTRA_SUPER_CLASS", subClassObject);
    }

}
/*超级类*/
抽象类超类
可包裹的器具{
受保护超类(包裹中){
mSuperId=in.readLong();
}
@凌驾
公共无效写入包裹(包裹目的地,内部标志){
目标写长(mSuperId);
}
}
/*子类*/
公共类子类
扩展超类{
受保护子类(包裹中){
超级(in),;
mSubId=in.readLong();
}
@凌驾
公共无效写入包裹(包裹目的地,内部标志){
超级可写包裹(目的地、旗帜);
目的地写长(mSubId);
}
@凌驾
公共int描述内容(){
返回0;
}
公共静态最终创建者=新创建者(){
@凌驾
公共子类createFromParcel(Parcel in){
返回新的子类(in);
}
@凌驾
公共子类[]newArray(整型大小){
返回新的子类[size];
}
};
}
/*用法*/
另一类{
void-aMethod(){
Bundle args=新Bundle();
args.putParcelable(“额外的超级类”,子类对象);
}
}

不幸的是,这没有多大帮助,因为我当前的结构需要在父类中实现一个
CREATOR
,为什么不将该行放在Animal的Parcel构造函数中?对于这种情况:我需要将猫、狗等(Animal的子类)的列表打包为类型为“Animal”的数组列表。在这种情况下,Animal的创建者将与writeToParcel中的数据一起使用,in.readString()用于确定类型,以便使用其parcel构造函数实例化正确的子类
package com.example.parcelable_example.model;

import android.os.Parcel;
import android.os.Parcelable;

public class Cat extends Animal{

    public Cat(String name){
        super(name, "Cat");
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(getType());
        super.writeToParcel(dest, flags);
    }

    public Cat(Parcel source) {
        super(source);      
    }

    public static final Parcelable.Creator<Cat> CREATOR = new Parcelable.Creator<Cat>() {
        public Cat createFromParcel(Parcel in) {
            /** DO NOT FORGET THIS!!! **/
            type = in.readString();
            return new Cat(in);
        }

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

}
/*   Super class   */

abstract class SuperClass
        implements Parcelable {

    protected SuperClass(Parcel in) {
        mSuperId = in.readLong();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(mSuperId);
    }

}



/*   Sub class   */

public class SubClass
        extends SuperClass {

    protected SubClass(Parcel in) {
        super(in);
        mSubId = in.readLong();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeLong(mSubId);
    }

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

    public static final Creator<SubClass> CREATOR = new Creator<SubClass>() {

        @Override
        public SubClass createFromParcel(Parcel in) {
            return new SubClass(in);
        }

        @Override
        public SubClass[] newArray(int size) {
            return new SubClass[size];
        }

    };

}



/*   Usage   */

class AnotherClass {

    void aMethod() {
        Bundle args = new Bundle();
        args.putParcelable("EXTRA_SUPER_CLASS", subClassObject);
    }

}