redstone-dart / redstone

A metadata driven microframework for Dart.
http://redstone-dart.github.io/redstone
MIT License
342 stars 42 forks source link

Use Factory Pattern to enable Polymorphism with a Hint Field #74

Open cgarciae opened 9 years ago

cgarciae commented 9 years ago

Say you have the abstract class

abstract class View
{
    @Id() String id;
    @Field() String name;
}

And the subclasses

class MultimediaView extends View
{
    @Field() List<String> imageUrlList;
}

class TextView extends View
{
    @Field() String text;
}

Given JSON and MongoDB's flexibility, it would be nice if you could have a JSON with a list Views and decoded to a List<View> like this

List<View> views = decodeJson (View, json);

but each view was decoded to a TextView or MultimediaView. I use a package in C# with uses a hint field and passes it to the parser. The hint field contains as a String the name of the class that object should be encoded to, and the hint is passes to the decoder as a parameter. So you have to change View to

abstract class View
{
    @Id() String id;
    @Field() String name;
    @Hint() String hint__;//Choose a rare name for the field
}

The hint field is passed like this to the decoder as an optional parameter

List<View> views = decodeJson (View, json, "hint__");

and a working example could be

json = """
[
    {
        "id" : "...",
        "name" : "...",
        "imageUrlList" : [...],
        "hint__" : "MultimediaView"
    },
    {
        "id" : "...",
        "name" : "...",
        "text" : "Some Text",
        "hint__" : "TextView"
    }  
]
""";

This way you can treat these object in a general way, store them in the same collection, move them around in together, have each override the abstract methods, etc.

luizmineo commented 9 years ago

This is a pretty cool feature indeed. I'll take a look at it and let you know.

cgarciae commented 9 years ago

@luizmineo Reflecting a little bit, since Redstone Mapper uses annotations it might not be necessary to pass the hint field name to decodeJson, instead have it "reflect" to see if the parent class (View in this case) has a parameter annotated with @Hint(), and if it does use that name. In case no hint field is provided, just decode to the parent class as normal.

cgarciae commented 9 years ago

Just checked an JsonFx (the C# library) doesn't use a hint field on the class, the field appears on the json when encoded, and it is expected when decoded, but the actual object doesn't contain it.