1

I use composite classes to group functionalities.
But, the class A (with composite A1), got inherited by B (with composite B1), and a behavior existent at A1 is going to be adapted at B1, but the final a1 must be a B1 instance for this to work.

Obs.: I have ways to make sure the composite instantiation happens properly (only by its composite partner).

Unable to assign a B1 object to a1 final field:

class finalFieldTestFails{
    class A1{
      A1(A a){}
    }

    class A{
      protected final A1 a1;
      A(){
        this.a1 = new A1(this);
      }

      A(A1 a1){
        this.a1 = a1;
      }
    }

    class B1 extends A1{
      B1(B b){
        super(b);
      }
    }

    class B extends A{
        //B(){ super.a1=new B1(this); } //FAIL: cant change final value
        //B(){super(new B1(this));} //FAIL: cant use 'this' or 'super'
    }
}

PS.: the answer shall not involve reflection security tricks if possible.

Community
  • 1
  • 1
Aquarius Power
  • 3,729
  • 5
  • 32
  • 67
  • 1
    It might help if you can explain what it is that you're trying to do, maybe with an example that's easier to follow? Otherwise it looks like your example as it stands is confirming expected behavior per the Java Language Spec... so, if this doesn't answer your question then maybe you need to reword your question? – Kevin Hooke Jan 16 '16 at 01:20
  • @KevinHooke thats the problem, I couldnt find an easier way to write it, that is the minimal, may be if I format it better? also I explained at the top how I need it to work. I am almost sure there is a way to overcome that without using reflection with security calls. – Aquarius Power Jan 16 '16 at 01:27
  • 1
    Maybe a better question is why do you need to structure your code like this, and why can't you structure it in a way that works per expected behavior. Is this your code or someone elses? If it's your code then can't you change your approach/design? – Kevin Hooke Jan 16 '16 at 01:31
  • @KevinHooke is mine. The design is intended to group functionalities, and to prevent myself, by mistake, at so many classes with so many concepts, from using the composite class in another non-friendly class, instead of moving its functionalities to a new miscellaneous class. The composite could simply be inside its friend class, but that would bloat the text file code. May be, a better IDE could help on not having to use composite classes, but I am too used to eclipse by now... (I really like it despite of this limitation) – Aquarius Power Jan 16 '16 at 01:37
  • I think you need to accept that you cannot change the value of a final field after it has been assigned. If you do need to do this for your given usecase, then you have to make this field non-final. – Kevin Hooke Jan 16 '16 at 01:39
  • 1
    See this similar question - are you looking for something like this? (see the first answer) http://stackoverflow.com/questions/663512/in-java-why-cant-i-declare-a-final-member-w-o-initializing-it-in-the-parent?rq=1 – Kevin Hooke Jan 16 '16 at 01:47
  • 1
    @KevinHooke perfect! I got it working with [this](http://stackoverflow.com/a/663533/1422630)! – Aquarius Power Jan 16 '16 at 02:49

2 Answers2

1

B(){ super.a1=new B1(this); } //FAIL: cant change final value

You can not assign values to already assigned final variables, You can instantiate it within the constructor but not as following.

B(){super(new B1(this));} //FAIL: cant use 'this' or 'super'

You can use this once the instance is created only. Since there is a inheritance tree, it is not completely instantiated, So the compiler complains,

cannot reference this before supertype constructor has been called

diyoda_
  • 5,274
  • 8
  • 57
  • 89
  • I cannot do it that way I exposed, but I need to do it in some way to not break the composite access restriction functionality. So I am trying to find another way that does not involve reflection security. – Aquarius Power Jan 16 '16 at 01:29
1

With this tip, given by @KevinHooke, I found this answer and I came with this code below.

But be aware that this option I chose may cause trouble.

So I ended up using an overriden method to instantiate the "1" kind, letting the super class take care of the assignment.

class finalFieldTestWorks{
    class A1{A1(A a){}}

    class A{
      protected final A1 a1;
      A(){
        this.a1=new1();
      }
      protected A1 new1(){return new A1(this);}
    }

    class B1 extends A1{B1(B b){super(b);}}

    class B extends A{
      B(){
        super();
      }
      @Override
      protected B1 new1(){return new B1(this);}
    }
}

PS.: Other tips/workarounds will be appreciated.

Community
  • 1
  • 1
Aquarius Power
  • 3,729
  • 5
  • 32
  • 67