-
Notifications
You must be signed in to change notification settings - Fork 651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Polymorphic Type Handling #334
Comments
@s3xy4ngyc making abstraction still won't save you from null as
but this check is still valid @martijnwalraven Any thoughts regarding this? |
@sav007 there is no need for having Hero as field in the Hero class. You actually just call It gets clearer when we are talking about Lists. (for Hero h in response.data().movie().heroes()) {
if(h.asHuman() != null { print(h.asHuman().getClass().getSimpleName());}
if(h.asDroid() != null { print(h.asDroid().getClass().getSimpleName());}
} As of when we would directly instantiate the Subtypes we would end up having something like this: (for Hero h in response.data().movie().heroes()) {
print(h.getClass().getSimpleName());
} |
@s3xy4ngyc unfortunately this idea is not valid for Unions. So there are 2 ways to get heterogeneous list like we have for With interfaces everything seems ok, we have parent interface But for unions you can mix any objects, that don't require to have the same parent interface. So the parent for such classes will be |
@sav007 Checked with the interface types:
Where |
@AlexWih sorry for confusion but I described the possible scenarios But the whole point is there is no way we can make solution that will work for both cases: with interfaces and with unions. |
@sav007: Maybe I don't understand the issue, but couldn't you just generate an abstract class for a union and have the possible types extend it, just as you would for a field of an interface type? In the code you proposed above, I don't think it matters whether the type of Another way of looking at it is that you wouldn't want to generate an interface for |
Agree, makes sense. Question: our apollo-codegen doesn't provide any information regarding parent interface
To support correctly polymorphic types with parent interface we need to update code gen module, right? |
@sav007: The IR should also contain the parent field type and fields that are not part of an inline fragment. So for a query like: query HeroForEpisode($episode: Episode) {
hero(episode: $episode) {
name
... on Human {
height
}
... on Droid {
primaryFunction
}
}
} The IR should contain:
Note that this is different than the query you specified, where query HeroForEpisode($ep: Episode!) {
hero(episode: $ep) {
... on Droid {
name
}
... on Human {
name
}
}
} Something else to think about is that we currently only expose |
Do you have an issue for this? or should we create new one under codegen project? |
Per our today discussion, we decided to put this issue on hold, as to implement it right we need to rethink from architecture of apollo codegen perspective to support GraphQL interfaces as well |
Change the way how inline fragments are been generated. Current implementation generates `synthetic` fields like `asHuman`, `asDroid` with duplicated fields copied from the GraphQL interface type. The new way is to generate them as polymorphic types. For example instead of this: ``` public static class Hero { final Optional<AsHuman> asHuman; final Optional<AsDroid> asDroid; } ``` Generate this: ``` public interface Hero { ... } public static class AsHuman implements Hero { ... } public static class AsDroid implements Hero { ... } ``` Closes apollographql#334
Change the way how inline fragments are been generated. Current implementation generates `synthetic` fields like `asHuman`, `asDroid` with duplicated fields copied from the GraphQL interface type. The new way is to generate them as polymorphic types. For example instead of this: ``` public static class Hero { final Optional<AsHuman> asHuman; final Optional<AsDroid> asDroid; } ``` Generate this: ``` public interface Hero { ... } public static class AsHuman implements Hero { ... } public static class AsDroid implements Hero { ... } ``` Closes #334
Currently the Codegeneration puts Type Instances as fields to an Generic Object.
To make it more clear here is an Example:
For a query like:
we do get the following Generated as Java Code:
This makes detection of Subtypes not convenient as you always have to check weather the return type of
as<type>()
is null. In my opinion usingthing.instanceOf(Clazz.class)
produces better code.My suggestion is to change the generic class to abstract and create instances of the mapped subtypes, so the generated Java Classes would look something like this:
The text was updated successfully, but these errors were encountered: