In Java, why can't I declare a final member (w/o initializing it) in the parent class and set its value in the subclass? How can I work around?

前端 未结 8 1249
长情又很酷
长情又很酷 2020-12-07 01:29

In a Java program, I have multiple subclasses inheriting from a parent (which is abstract). I wanted to express that every child should have a member that is set once only (

相关标签:
8条回答
  • 2020-12-07 01:49

    I would do it like this:

    public abstract class Parent 
    {
        protected final String birthmark;
    
        protected Parent(final String mark)
        {
            // only if this makes sense.
            if(mark == null)
            {
                throw new IllegalArgumentException("mark cannot be null");
            }
    
            birthmark = mark;
        }
    }
    
    public class Child 
        extends Parent 
    {
        public Child(final String s) 
        {
            super(s);
        }
    }
    

    final means that the variable can be initialized once per instance. The compiler isn't able to make sure that every subclass will provide the assignment to birthmark so it forces the assignment to happen in the constructor of the parent class.

    I added the checking for null just to show that you also get the benefit of being able to check the arguments in one place rather than each cosntructor.

    0 讨论(0)
  • 2020-12-07 01:49

    You probably want to have a Parent(String birthmark) constructor so that you can ensure in your Parent class that final is always initialized. Then you can call super(birthmark) from your Child() constructor.

    0 讨论(0)
  • 2020-12-07 01:57

    You can't do it because while comparing the parent class, the compiler can't be sure that the subclass will initialize it. You'll have to initialize it in the parent's constructor, and have the child call the parent's constructor:

    public abstract class Parent {
        protected final String birthmark;
        protected Parent(String s) {
            birthmark = s;
        }
    }
    
    public class Child extends Parent {
        public Child(String s) {
            super(s);
            ...
        }
    }
    
    0 讨论(0)
  • 2020-12-07 02:02

    Why not delegate initialization to a method. Then override the method in the parent class.

    public class Parent {
       public final Object x = getValueOfX();
       public Object getValueOfX() {
          return y;
       }
    }
    public class Child {
      @Override
      public Object getValueOfX() {
         // whatever ...
      }
    }
    

    This should allow custom initialization.

    0 讨论(0)
  • 2020-12-07 02:04

    Pass it to the parent constructor:

    public abstract class Parent {
        private final String birthmark;
        public Parent(String s) {
            birthmark = s;
        }
    }
    
    public class Child extends Parent {
        public Child(String s) {
            super(s);
        }
    }
    
    0 讨论(0)
  • 2020-12-07 02:04

    Declare a constructor in the superclass that's called by the subclass. You must set the field in the superclass to make sure it's initialized, or the compiler can't be sure the field is initialized.

    0 讨论(0)
提交回复
热议问题