2

Problem Description

I have Category class which implements Parcelable, also I have few more classes which are extended from the Category class. My base class has 2 protected members title and id which are set mainly from the inherited classes. So in order not to implement Parcelable related stuff everywhere in the inherited classes I decide to do it in a base class and let it handle all actions.

Question

The problem is that I can't have constructor of Category class as it is abstract class. So what is the solution? As I have abstract methods in the class I can't remove abstract modifier.

Source code

public abstract class Category implements Parcelable {
    private static Map<Integer, Category> categoryMap = new TreeMap<Integer, Category>();

    protected Sting title;
    protected Integer  id;

    static {
        categoryMap.put(0, new Taxi());
        categoryMap.put(1, new Hotel());
    }

    private Category(Parcel in) {
        this.id = in.readInt();
        this.title = in.readString();
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInteger(id);
        dest.writeString(title);
    }
    
    public static final Parcelable.Creator<Category > CREATOR = new Parcelable.Creator<Category >() {
        public Category createFromParcel(Parcel in) {
            return new Category (in);  <=== !!! THIS IS NOT ALLOWED AS CLASS IS ABSTRACT !!!
        }                          

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

    abstract void generateCodes();
    abstract String getImageIcon();
    
};

public final class Taxi extends Category {

    public Taxi() {
        title = "taxi";
        id = 1547845;
    }

};

public final class Hotel extends Category {

    public Hotel() {
        title = "hotel";
        id = 1397866;
    } 

};
Community
  • 1
  • 1
Victor Apoyan
  • 67
  • 1
  • 8

1 Answers1

8

It is possible to have constructors in abstract classes, and you can do the parceling there - just make sure you call the respective super(...) method in the child classes. Check this out.

EDIT: I think Category does not need to implement CREATOR as you cannot instantiate it...? Similar suggestions are here and here

public abstract class Category implements Parcelable {
    private static Map<Integer, Category> categoryMap = new TreeMap<Integer, Category>();

    protected String title;
    protected Integer  id;

    static {
        categoryMap.put(0, new Taxi());
        categoryMap.put(1, new Hotel());
    }

    protected Category(){}

    protected Category(Parcel in) {
        this.id = in.readInt();
        this.title = in.readString();
    }

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

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

    abstract void generateCodes();
    abstract String getImageIcon();

};

public final class Taxi extends Category {
    public Taxi() {
        title = "taxi";
        id = 1547845;
    }

    protected Taxi(Parcel in) {
        super(in);
    }

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

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

public final class Hotel extends Category {
    public Hotel() {
        title = "hotel";
        id = 1397866;
    }

    protected Hotel(Parcel in) {
        super(in);
    }

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

        public Category [] newArray(int size) {
            return new Hotel[size];
        }
    };
};
Community
  • 1
  • 1
sfThomas
  • 1,701
  • 2
  • 14
  • 25
  • `public Category createFromParcel(Parcel in) { return new Category(in);}` But I want call it not in child class but in base class itself. – Victor Apoyan Sep 05 '14 at 13:18
  • Updated the answer with a code sample - but true that it specifies the CREATOR twice. If you want to put the creator in the base class, then that itself must know about its children, which is technically doable, but is not a really good pattern. – sfThomas Sep 05 '14 at 13:23
  • 1
    sorry I can rate you +1 as my reputation is low, +1 to you, thanks for answer, it's really help me. – Victor Apoyan Sep 05 '14 at 13:35