0

So I have this abstract class

 public abstract class A {

   protected final boolean b;

   protected A (boolean b){
    this.b = b;
   }

}

And this class that extends A

 public class C extends A{

   protected C() {
    super(false);
   }

}

I dont want "b" to be able to change its' value once it's initialized But I dont know how to do it without the compiler going haywire.

Any suggestions are welcome. Thanks in advance.

EDIT1: static removed from b.

EDIT 2: Ok realised the problem and fixed see above. Special thanks to J.Lucky :)

Mechanic45
  • 173
  • 1
  • 6
  • 16
  • 2
    Why is a *static* variable being set by an *instance* method? That sounds like a bad idea to start with. It would help if you'd give a reason why you're trying to get this design to work. – Jon Skeet Sep 12 '14 at 00:21
  • Basically it is a variable that is going to be present in every child class, but in each of them may have a different value EDIT: I added static because the compiler was complaining basicaly – Mechanic45 Sep 12 '14 at 00:24
  • Well then a single static variable isn't going to help you anyway, is it? That will have *one* value, however many subclasses you have. – Jon Skeet Sep 12 '14 at 00:26
  • Yes I realised that just now :P I'll correct that thanks – Mechanic45 Sep 12 '14 at 00:27

3 Answers3

3

I'd suggest you make use of the final keyword.

Try the following codes:

abstract class A {

    final protected boolean b;

    A(boolean b) {
        this.b = b;
    }

    //No setter method
    //public abstract void setB(boolean b);
    public abstract boolean getB();
}

class C extends A {

    C(boolean b) {
        super(b);
    }

    @Override
    public boolean getB() {
        return b;
    }
}

Sample implementation would be:

public static void main(String args[]) {
    C c = new C(true);
    System.out.println(c.getB());
}

Since b now is a final variable, you will be forced to initialize it on your constructor and you will not have any way of changing b anymore. Even if you provide a setter method for b, the compiler will stop you.

EDIT 2:

Say you created another class called 'D' and this time you know you want to set it to false by default. You can have something like:

class D extends A {
    D() {
        super(false);
    }

    //You can also overload it so that you will have a choice
    D(boolean b) {
        super(b);
    }


    @Override
    public boolean getB() {
        return b;
    }

    public static void main(String[] args) {
        D defaultBVal = D();
        D customBVal = D(true);

        System.out.println(defaultBVal.getB()); //false
        System.out.println(customBVal.getB()); //true
    }
}
lxcky
  • 1,668
  • 2
  • 13
  • 26
  • I think you lost me there, since it's NOT a final variable isn't it possible that it could change vlaue? – Mechanic45 Sep 12 '14 at 00:33
  • @Mechanic45, Okay, I've changed it. I set `b` as `final` now. This should address your concern. – lxcky Sep 12 '14 at 00:41
  • Oh! and this way if I add more "common variables" I can just add them in one constructor and just adjust the args.So it is safe to not declare them final AND not worry :P. Thanks a lot it helped tremendus-iously! :) – Mechanic45 Sep 12 '14 at 00:42
  • @Mechanic45, I declare `b` as `final` now so that you won't be allowed to set it again. – lxcky Sep 12 '14 at 00:50
  • 1
    @Mechanic45 Say you have a Class D and you already know that you want to set it to false. What you can do is this: `D() { super(false) }` You don't have to asked them to provide the value of `b` in your constructor anymore. – lxcky Sep 12 '14 at 01:06
0

Solution: You should change the boolean into a Boolean, make it private, provide a getter and a protected setter. In the setter you should check whether the Boolean has been initialized. If so, you should either ignore resetting, or throw and Exception

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
  • 1
    you will also need synchronization here and you will need to synchronize on ```A.class``` – Mateusz Dymczyk Sep 12 '14 at 00:26
  • @ControlAltDel it is possible that there could be many child classes to A so memory-wise wouldn't be a little costly to use Boolean instead of the primitive type? – Mechanic45 Sep 12 '14 at 00:38
  • This is what programmers do - always pre-optimizing for problems that may never happen... If you EVER run into that case (highly unlikely) then we'll talk – ControlAltDel Sep 12 '14 at 05:32
0

well how about this:

public abstract class A {

   private static Boolean b;

   //setB is declared here and, depending on the class that implements it, 
   //it initializes the value of the variable "b"

   protected abstract void setB();

}

public class C extends A{

   protected void setB() {
     if(b != null) b = true;
   }
}

Now the variable is only initialized once when its called. There are still some problems. Someone could use reflection to change the value. Also, when the object is serialized is possible that someone could change the value. If you have a multiple threads accessing this then you should synchronize the method. However, if these aren't issues then this solution might work for you.

user2122031
  • 581
  • 5
  • 11