En Java, pourquoi ne puis-je pas déclarer un membre final (sans l'initialiser) dans la classe parente et définir sa valeur dans la sous-classe? Comment puis-je travailler?

StackOverflow https://stackoverflow.com/questions/663512

  •  20-08-2019
  •  | 
  •  

Question

Dans un programme Java, j'ai plusieurs sous-classes héritant d'un parent (ce qui est abstrait). Je voulais dire que chaque enfant devrait avoir un membre qui est défini une seule fois (ce que je prévoyais de faire du constructeur). Mon plan était de coder comme ceci:

public abstract class Parent {
    protected final String birthmark;
}

public class Child extends Parent {
    public Child(String s) {
        this.birthmark = s;
    }
}

Cependant, cela ne semble pas plaire aux dieux de Java. Dans la classe parente, je reçois le message que birthmark & "; N'a peut-être pas été initialisé &" ;, dans la classe enfant, je reçois & "; Le champ final <=> est inaccessible < !> quot;.

Alors, quelle est la méthode Java pour cela? Qu'est-ce qui me manque?

Était-ce utile?

La solution

Vous ne pouvez pas le faire car, lors de la comparaison de la classe parent, le compilateur ne peut pas être sûr que la sous-classe l'initialisera. Vous devrez l'initialiser dans le constructeur du parent et demander à l'enfant d'appeler le constructeur du parent:

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);
        ...
    }
}

Autres conseils

Transmettez-le au constructeur parent:

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);
    }
}

Une autre méthode Java-ish consiste à faire en sorte que la classe parent définisse un & abstraite getter " et que les enfants l’implémentent. Dans ce cas, ce n’est pas une bonne façon de le faire, mais dans certains cas, cela peut être exactement ce que vous voulez.

Je le ferais comme ceci:

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 signifie que la variable peut être initialisée une fois par instance. Le compilateur n'est pas en mesure de s'assurer que chaque sous-classe fournira l'affectation à la marque de naissance, ce qui oblige celle-ci à se produire dans le constructeur de la classe parente.

J'ai ajouté la vérification de la valeur null pour montrer que vous bénéficiez également de la possibilité de vérifier les arguments à un endroit plutôt qu'à chaque cosntructeur.

Pourquoi ne pas déléguer l’initialisation à une méthode. Remplacez ensuite la méthode dans la classe parent.

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

Ceci devrait permettre une initialisation personnalisée.

Oui, les membres finaux doivent être affectés à la classe dans laquelle ils sont déclarés. Vous devez ajouter un constructeur avec un argument String à Parent.

Déclarez un constructeur dans la superclasse appelée par la sous-classe. Vous devez définir le champ dans la superclasse pour vous assurer qu'il est initialisé, sinon le compilateur ne peut pas être sûr que le champ est initialisé.

Vous voudrez probablement avoir un constructeur Parent (String birthmark) afin de vous assurer que, dans votre classe Parent, la version finale est toujours initialisée. Ensuite, vous pouvez appeler super (marque de naissance) depuis votre constructeur Child ().

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top