stag-java icon indicating copy to clipboard operation
stag-java copied to clipboard

Stag cannot access inherited members if the classes are in different packages

Open anthonycr opened this issue 8 years ago • 3 comments

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.

anthonycr avatar Feb 15 '17 02:02 anthonycr

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.

anthonycr avatar Feb 15 '17 02:02 anthonycr

Agree with you that in these cases we should just enforce public methods.

yasirmhd avatar Feb 21 '17 18:02 yasirmhd

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.

anthonycr avatar Feb 22 '17 14:02 anthonycr