67 votes

Référence directe illégale et Enums

Je suis en train de programmer un jeu en java qui est constitué d'une grille de tuiles. Je veux pouvoir définir de manière intuitive les bords des tuiles et la manière dont ils se rapportent les uns aux autres, par exemple, pour obtenir le bord opposé d'une tuile, je veux pouvoir simplement taper TOP.opposite() . Cependant, lorsque j'utilise des enums pour définir ces bords, je finis par devoir faire référence à au moins deux d'entre eux dans le contstructeur :

public enum Edge {

   TOP(Edge.BOTTOM), //illegal forward reference
   BOTTOM(Edge.TOP),
   LEFT(Edge.RIGHT), //illegal forward reference
   RIGHT(Edge.LEFT);

   private Edge opposite;

   private Edge(Edge opp){
      this.opposite = opp;
   }

   public Edge opposite(){
      return this.opposite;
   }
}

Existe-t-il un moyen de contourner ce problème en utilisant les enums de manière tout aussi simple ?

92voto

Peter Lawrey Points 229686

Vous pouvez le faire, ce qui n'est pas aussi intuitif.

public enum Edge {
    TOP, BOTTOM, LEFT, RIGHT;
    private Edge opposite;

    static {
        TOP.opposite = BOTTOM;
        BOTTOM.opposite = TOP;
        LEFT.opposite = RIGHT;
        RIGHT.opposite = LEFT;
    }
    public Edge opposite(){
        return this.opposite;
    }
}

0 votes

Malheureusement, si l'enum est nécessaire dans l'initialisateur statique d'une autre classe, vous pouvez obtenir l'exception suivante class .....EnumName not an enum . Je vais devoir utiliser Maps...

0 votes

@P.Péter Il ne devrait y avoir aucun problème à utiliser un Enum n'importe où dans une autre classe, un initialisateur statique ou n'importe où ailleurs.

0 votes

@PeterLawrey Vous avez raison, j'ai fait une autre erreur qui a entraîné l'exception mentionnée. Votre solution fonctionne parfaitement !

24voto

Vitaliy Oliynyk Points 11
enum Edge {
    TOP {
        @Override
        public Edge opposite() {
            return BOTTOM;
        }
    },
    BOTTOM {
        @Override
        public Edge opposite() {
            return TOP;
        }
    },
    LEFT {
        @Override
        public Edge opposite() {
            return RIGHT;
        }
    },
    RIGHT {
        @Override
        public Edge opposite() {
            return LEFT;
        }
    };

    public abstract Edge opposite();
}

10voto

jacktrades Points 1424

Vous pouvez également faire appel à un classe interne statique à l'intérieur de l'enum :

public enum EnumTest     
{     
NORTH( Orientation.VERTICAL ),     
SOUTH( Orientation.VERTICAL ),     
EAST( Orientation.HORIZONTAL ),     
WEST( Orientation.HORIZONTAL );     

private static class Orientation  
{  
private static final String VERTICAL = null;     
private static final String HORIZONTAL = null;     
}
}

Volé à aquí :)

9voto

BalusC Points 498232

Voici un autre moyen

public enum Edge {

    TOP("BOTTOM"),
    BOTTOM("TOP"),
    LEFT("RIGHT"),
    RIGHT("LEFT");

    private String opposite;

    private Edge(String opposite){
        this.opposite = opposite;
    }

    public Edge opposite(){
        return valueOf(opposite);
    }

}

La solution de Peter Lawrey est cependant plus efficace et plus sûre pour le temps de travail.

7voto

Jeff Foster Points 22175

Ajouter une méthode opposite pour retourner l'objet de l'énumération

Vous pourriez simplement définir une méthode, opposite() .

En Java moderne, l'expression switch

En Java moderne, nous pouvons utiliser un expression de commutation . Le compilateur s'assure que nous avons couvert tous les cas possibles.

enum Edge
{
    TOP, BOTTOM, LEFT, RIGHT;

    public Edge opposite ( )
    {
        return switch ( this )
                {
                    case TOP -> BOTTOM;
                    case BOTTOM -> TOP;
                    case LEFT -> RIGHT;
                    case RIGHT -> LEFT;
                };
    }
}

Utilisation :

System.out.println( Edge.TOP.opposite() );

BOTTOM

Dans les versions antérieures de Java, switch

Dans les anciens Java, utilisez la syntaxe vue dans le code suivant.

Notez la nécessité d'un default au cas où vous ajouteriez un élément à l'énumération ou que vous supprimeriez par inadvertance un cas de l'énumération. switch .

public enum Edge {
    TOP,
    BOTTOM,
    LEFT,
    RIGHT;

    public Edge opposite() {
        switch (this) {
            case TOP:
                return BOTTOM;
            case BOTTOM:
                return TOP;
            case LEFT:
                return RIGHT;
            case RIGHT:
                return LEFT;
            default:
                throw new RuntimeException("Oh dear");
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X