mercredi 24 juillet 2019

How do you dynamically get subclasses in an inheritance hierarchy when there are derived classes mainly for extending state not for behaviour?

I am trying to consume my tumblr data by using Jumblr which is a Tumblr API wrapper client for Java.

I have studied the source code and have seen that since Json response is dynamic, there is a Post POJO and derived POJOs like TextPost, QuotePost, PhotoPost etc. to deserialize to pojos. It handles consuming in a generic way by using Gson with a custom deserializer which uses reflection. In this way, for example it deserializes a Json response to a TextPost and assigns it to Post object.

So in order to get subclass' field, I need to downcast Post object after instanceof checks like this:

List<Post> posts =  blog.draftPosts();
Post post = posts.get(0); //gets a TextPost
if(post instanceof TextPost) {
    System.out.println("title: " + ((TextPost) post).getTitle());
    System.out.println("body: " + ((TextPost) post).getBody()); 
}
else if(post instanceof QuotePost) {
    //...
}
else if...

I am not sure this is the best way. So I am searching for more elegant or a best way or a correct way from the perspective of object-oriented programming concepts like polymorphism or others.

What is the right approach to get subclass or access to it from a superclass?

How do you evaluate API's object oriented design which uses inheritance by extending specific classes which contain extra state? Is it a reasonable approach and what are the other ways from the perspective of the client which will be handling response? Since it is not behavior inheritance, is it right to use inheritance to only inherit state?

From the API source:


public class Post {
    protected PostType type;
    private Long id;
    private String author;
    private String reblog_key;
    private String blog_name;
    //more state and getters/setters
}

public class TextPost extends Post {
    //extra fields
    private String title;
    private String body;

    //getters/setters
}


public List<Post> getPosts() {
    Gson gson = gsonParser();
    JsonObject object = (JsonObject) response;
    List<Post> l = gson.fromJson(object.get("posts"), new 
                        TypeToken<List<Post>>() {}.getType());
    ...
}

private Gson gsonParser() {
        return new GsonBuilder().
            registerTypeAdapter(Post.class, new PostDeserializer()).
            create();
    }

public class PostDeserializer implements JsonDeserializer<Object> {

    @Override
    public Object deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
        JsonObject jobject = je.getAsJsonObject();
        String typeName = jobject.get("type").getAsString();
        String className = typeName.substring(0, 1).toUpperCase() + typeName.substring(1) + "Post";
        try {
            Class<?> clz = Class.forName("com.tumblr.jumblr.types." + className);
            return jdc.deserialize(je, clz);
....

}


Aucun commentaire:

Enregistrer un commentaire