7 Replies Latest reply: Nov 9, 2011 3:42 AM by 802930 RSS

    Enforce setting private variable in subclass with abstract method

    802930
      Hi,

      Is this something that is common usage/practice?:
      public abstract class Base {
          private int importantPrivateVariable = setImportantPrivateVariable();
          protected abstract int setImportantPrivateVariable();
      }
      I would like to enforce the extender of the class to set a private variable, but as there is no abstract variable in java, I can only use a method for it.

      Thanks,
      lemonboston

      Edit: the variable could be protected as well, I suppose this is not important here, but correct me if I am wrong
        • 1. Re: Enforce setting private variable in subclass with abstract method
          gimbal2
          I would expect this 'important private variable' to be passed in through the constructor. An abstract class can have one.
          • 2. Re: Enforce setting private variable in subclass with abstract method
            802930
            gimbal2 wrote:
            I would expect this 'important private variable' to be passed in through the constructor. An abstract class can have one.
            And what if I don't want the user of the subclass to bother with this variable when instantiating this class? I would like to encapsulate the value of this variable in the subclass.

            Edit: To clear up a bit what I mean:
            - i would like to make sure that when a subclass is written, this variable is set for that subclass
            ( - but when somebody create an object of this subclass they don't need to bother with it)
            This is a subclass specific value but it is only used internally within that class.

            Edited by: lemonboston on Nov 7, 2011 4:01 AM

            Edited by: lemonboston on Nov 7, 2011 4:07 AM
            • 3. Re: Enforce setting private variable in subclass with abstract method
              DrClap
              Well, you can certainly force the subclass to implement that method. But you can't force the subclass to call the method. Whereas if your abstract class provided only a single constructor, into which the "important" variable had to be passed, you would force the subclass to use that constructor.

              In general you can't force a subclass to have any particular behaviour at all. Document the requirements and move on. If the subclass doesn't conform to those requirements then maybe it won't work right. That isn't your problem.
              • 4. Re: Enforce setting private variable in subclass with abstract method
                jduprez
                lemonboston wrote:
                Hi,

                Is this something that is common usage/practice?:
                I don't think that's so common, but that's code easily understandable. However there are several problems with this approach:
                public abstract class Base {
                private int importantPrivateVariable = setImportantPrivateVariable();
                protected abstract int setImportantPrivateVariable();
                }
                I would like to enforce the extender of the class to set a private variable
                That's no what your code implements: your base class forces the subclasses to return an int value, and the Base class uses that value to assign it to the variable.

                Therefore the method should be called get<Something> (e.g. <TT>getInitialValueOfImportantVariable()</TT>+ to have a naming consistent with its signature (it returns a value, whereas a regular setter method should declare a void return type: <TT>protected abstract void setImportantPrivateVariable(int someValue);</TT>).
                Edit: the variable could be protected as well, I suppose this is not important here,
                Well, yes, this is "important" - at least, there a noticeable difference: the variable being private, the base class is free to handle it as it sees fit (e.g., assign the value at construction time and never modify it afterwards). If the variable was protected, the subclass could modify in ways and at times not known by the base class.
                but correct me if I am wrong
                There's a trap in this construct: the method is called in the variable initializer, that is, behind the scenes, approximately during the execution of the Base class constructor, so before the subclass constructor. So, you are calling a method on an object that is not fully initialized (e.g. some of its attributes may still be <TT>null</TT> at this stage). There is a rule that discourages such situations, that goes something like "don't call non-private and non-final methods from a constructor".

                To avoid this trap, two options:
                - require an int argument in the Base class's constructor , as was suggested above
                - don't get and set the value of the important variable in the initializer or constructor code, but from a special method in the base class instead:
                public abstract class Base {
                    private int importantPrivateVariable; // default value is zero
                // or alternatively: 
                //    private int importantPrivateVariable = ...; // Some default value
                    protected abstract int getImportantPrivateVariable();
                
                    public void initializeImportantPrivateVariable() {
                        importantPrivateVariable = getImportantPrivateVariable();
                    }
                }
                That construct is a degenerate form of a common design pattern known under the name of Template Method (where a base class method calls generally several subclass methods in a specified order and with a specified chaining, leaving it to the subclass to implement the details of the methods).

                The drawback is that the client code (the one that uses the Base instance) has to know when to call that initialization method, whereas the constructor-based initialization lets the client code free to not care at all.

                Much luck,

                J.
                • 5. Re: Enforce setting private variable in subclass with abstract method
                  802930
                  In general you can't force a subclass to have any particular behaviour at all. Document the requirements and move on. If the subclass doesn't conform to those requirements then maybe it won't work right. That isn't your problem.
                  Thank you DrClap, this is very useful! You grabbed my original motivation more clearly than me myself. It is very good to know I don't have to bother to design the abstract class around making sure that the subclass would work correctly; I can just leave it off. It will be much easier this way :). Thanks!
                  • 6. Re: Enforce setting private variable in subclass with abstract method
                    802930
                    Thank you jduprez! I will reply to your post in more detail when I have the time.
                    • 7. Re: Enforce setting private variable in subclass with abstract method
                      802930
                      >
                      Therefore the method should be called get<Something> (e.g. <TT>getInitialValueOfImportantVariable()</TT>+ to have a naming consistent with its signature (it returns a value, whereas a regular setter method should declare a void return type: <TT>protected abstract void setImportantPrivateVariable(int someValue);</TT>).
                      I've noticed this, I thought maybe assign could be used as a prefix here like assignValueOfImportantVariable()
                      There's a trap in this construct: the method is called in the variable initializer, that is, behind the scenes, approximately during the execution of the Base class constructor, so before the subclass constructor. So, you are calling a method on an object that is not fully initialized (e.g. some of its attributes may still be <TT>null</TT> at this stage). There is a rule that discourages such situations, that goes something like *"don't call non-private and non-final methods from a constructor"*.
                      Thank you jduprez for pointing this out and mentioning this 'rule'! I didn't think of it and now I see why this may be bad practive and should be avoided probably.

                      - require an int argument in the Base class's constructor , as was suggested above
                      Thanks for everyone who suggested this; I suppose this would work:
                      public abstract class Base {
                           
                           private int importantPrivateVariable;
                           
                           protected Base(int importantPrivateVariable){
                                this.importantPrivateVariable = importantPrivateVariable;
                           }
                           
                      }
                      -----
                      
                      public class SubClass3 extends Base {
                      
                           SubClass3(){
                                super(3);
                           }
                      
                      }
                      Template Method (where a base class method calls generally several subclass methods in a specified order and with a specified chaining, leaving it to the subclass to implement the details of the methods).
                      I've just learnt about it in the same project where this question occured to me, probably it is no coincidence :)
                      Much luck,
                      J.
                      cheers,
                      lemonboston