2
votes

Comment diviser une chaîne avant d'appeler un autre constructeur

J'essaye de réutiliser mon constructeur comme ceci:

    public final long x;
    public final long y;
    public final int level;
    private final int hash;
    public final Point tileCenter;

    public TileCoordinate(long x, long y, int level) {
        this.x = x;
        this.y = y;
        this.level = level;
        this.hash = Objects.hash(x, y, level);
        this.tileCenter = getTileCenter();
    }

    public TileCoordinate(String key) {
        String[] bits = key.split("-");
//      this.level = Integer.parseInt(bits[0]);
//      this.x = Long.parseLong(bits[1]);
//      this.y = Long.parseLong(bits[2]);
        this(Long.parseInt(bits[0]),Long.parseLong(bits[1]),Integer.parseLong(bits[2]));
        this.hash = Objects.hash(x, y, level);
        this.tileCenter = getTileCenter();
    }

Puisque je ne veux pas écrire this (Integer.parseInt (key.split ("-") [0 ]), Long.parseLong (key.split ("-") [1]), Long.parseLong (key.split ("-"))); , quelles sont mes options?


6 commentaires

Pourriez-vous clarifier ce que signifie puisque je ne veux pas répéter key.split pour chaque paramètre ? Vous n'avez qu'un seul paramètre correct?


non, je veux dire que je ne veux pas écrire ceci (Integer.parseInt (key.split ("-") [0]), Long.parseLong (key.‌ split ("-") [1]), Long.‌ parseLong (key.split (‌ "-")));


Est-ce parce que l'appel à this doit être la première instruction d'un constructeur, s'il existe?


oui c'est le problème


Que diriez-vous plutôt d'une méthode d'usine statique?


Je suppose que vous pourriez avoir une méthode setParam () pour faire exactement ce que fait votre constructeur sans qu'il soit un constructeur.


3 Réponses :


4
votes

Il semble que vous ne faites que cette ligne String [] bits = key.split ("-"); pour éviter d'avoir à l'appeler 3 fois dans l'appel du constructeur différé à this () , qui, s'il existe, doit être la première instruction d'un constructeur.

Au lieu de déléguer à un constructeur pour l'affectation réelle du champ, déléguez à un private méthode qui gère les attributions de champ.

public TileCoordinate(String key) {
    String[] bits = key.split("-");
    init(Long.parseInt(bits[0]),Long.parseLong(bits[1]),Integer.parseInt(bits[2]));
    this.hash = Objects.hash(x, y, level);
    this.tileCenter = getTileCenter();
}

private void init(long x, long y, int level) {
    // assign to fields here
}

Assurez-vous qu'il est privé afin qu'il ne puisse pas être remplacé, où fuite ce code > deviendrait un problème.

Vous pouvez également vérifier que bits contient 3 éléments avant de continuer.


2 commentaires

Mais les champs sont définitifs, j'ai oublié de dire ça


Eh bien, maintenant que vous avez révélé que vos champs sont définitifs , cela ne fonctionnera pas. Dans ce cas, une méthode d'usine serait la voie à suivre.



3
votes

L'appel à this () ou super () doit être la première instruction du constructeur. Une façon de résoudre ce problème serait de convertir le deuxième constructeur en une Méthode d'usine :

public static TileCoordinate parseTitleCoordinate(String key) {
  String[] bits = key.split("-");
  long x = Long.parseLong(bits[0]);
  long y = Long.parseLong(bits[1]);
  long level = Long.parseLong(bits[2]);
  return new TitleCoordinate(x, y, level);
}

Cela permettrait de conserver les champs final.


1 commentaires

Pourquoi super () est-il nécessaire?



0
votes

Pourrait surcharger une méthode init:

  public TileCoordinate(long x, long y, int level) {
      init(x, y, level);
  }

  public TileCoordinate(String key) {
      init(key);
  }

  private void init(String key) { 
      String[] bits = key.split("-");
      init(Long.parseLong(bits[0]),
           Long.parseLong(bits[1]),
           Integer.parseInt(bits[2]));
  }

  private void init(long x, long y, int level) { 
      this.setX(x);
      this.setY(y);
      this.setLevel(level);
  }

Cela maintient une seule responsabilité. Seule la 2ème méthode init appelle les setters, le reste délègue.


0 commentaires