stag-java
stag-java copied to clipboard
Stag cannot access inherited members if the classes are in different packages
Issue Summary
If ClassA
extends ClassB
and inherits fields, stag will collect all the inherited fields and use them in the creation of an object. If ClassA
extends ClassB
, which is in a different package than ClassA
, and the members of ClassB
are protected or package local (legal according to stag rules), then the type adapter for ClassA
will not be able to access them.
Reproduction Steps
Take the following two classes. The generated ClassA$TypeAdapter
will not be able to access field2
.
package sample.a;
@UseStag
class ClassA extends ClassB {
protected String field1;
}
package sample.b;
@UseStag
class ClassB {
protected String field2;
}
Expected Behavior
Stag should either be able to access the fields, or should enforce a rule requiring classes that are extended to make their members public.
Actual Behavior
Given the example above, the generated ClassA$TypeAdapter
will not be able to access field2
.
A possible solution I'll put down before I forget it:
Since ClassB
has a valid type adapter that can access the forbidden fields, it's possible that we could change the way the ClassA
type adapter is generated. Instead of each type adapter re-adding all the field assignments, a type adapter could use the type adapter from the inherited type in order to fill its fields.
Basically...
class ClassB$TypeAdapter {
T <T extends ClassB> parse(Json, Instantiator<T>) {
T object = Instantiator.instantiate();
object.field2 = "stuff";
return object.
}
}
class ClassA$TypeAdapter {
ClassA parse(Json) {
ClassA object = ClassB$TypeAdapter.parse(Json, ClassA.instantiator);
object.field = "more stuff";
return object;
}
}
This seems potentially very complicated, so maybe it would be better to just enforce public fields if a descendent class type adapter can't access parent fields.
Agree with you that in these cases we should just enforce public methods.
Related to this bug, if a class has a static member class that is non-public, or itself is non-public, Stag will fail to compile as it cannot access the inner class from the generated Stag.class
.
@UseStag
public class ClassA {
@UseStag
static class ClassB {
String field.
}
}
The solution here is just to require a class annotated with @UseStag
to be public.