วิธี Java Enum - ส่งกลับทิศทางตรงกันข้าม enum


113

ฉันต้องการประกาศทิศทาง enum ซึ่งมีวิธีการที่ส่งกลับทิศทางตรงกันข้าม (ต่อไปนี้ไม่ถูกต้องตามไวยากรณ์กล่าวคือไม่สามารถสร้างอินสแตนซ์ enums ได้ แต่แสดงให้เห็นถึงจุดของฉัน) เป็นไปได้ใน Java หรือไม่?

นี่คือรหัส:

public enum Direction {

     NORTH(1),
     SOUTH(-1),
     EAST(-2),
     WEST(2);

     Direction(int code){
          this.code=code;
     }
     protected int code;
     public int getCode() {
           return this.code;
     }
     static Direction getOppositeDirection(Direction d){
           return new Direction(d.getCode() * -1);
     }
}

เพียงแค่ใช้สวิตช์ คุณมี 4 กรณีเท่านั้น
Sotirios Delimanolis

12
โดยวิธีการd.getCode() * -1==-d.getCode()
tckmn

บทที่ 6 (ใน 2E เป็นอย่างน้อย) ของEffective JavaของBlochอาจเป็นที่สนใจและแนะนำเป็นอย่างยิ่ง
jedwards

ntu.edu.sg/home/ehchua/programming/java/javaenum.htmlส่วน 2.1 ได้อธิบายแนวคิดอย่างเรียบร้อย
vikramvi

คำตอบ:


207

สำหรับผู้ที่ล่อมาที่นี่ด้วยชื่อ: ใช่คุณสามารถกำหนดวิธีการของคุณเองใน enum ของคุณ หากคุณสงสัยว่าจะเรียกใช้เมธอดแบบไม่คงที่ได้อย่างไรคุณจะทำเช่นเดียวกับวิธีการอื่นที่ไม่คงที่ - คุณเรียกใช้โดยใช้อินสแตนซ์ของประเภทที่กำหนดหรือสืบทอดวิธีการนั้น ในกรณีของ enums เช่นนี้เป็นเพียงENUM_CONSTANT s

EnumType.ENUM_CONSTANT.methodName(arguments)ดังนั้นสิ่งที่คุณต้องการคือ


ตอนนี้ให้กลับไปที่ปัญหาจากคำถาม หนึ่งในวิธีแก้ปัญหาอาจเป็นได้

public enum Direction {

    NORTH, SOUTH, EAST, WEST;

    private Direction opposite;

    static {
        NORTH.opposite = SOUTH;
        SOUTH.opposite = NORTH;
        EAST.opposite = WEST;
        WEST.opposite = EAST;
    }

    public Direction getOppositeDirection() {
        return opposite;
    }

}

ตอนนี้Direction.NORTH.getOppositeDirection()จะกลับDirection.SOUTHแล้ว.


ต่อไปนี้เป็นวิธีที่ " แฮ็ก " เพิ่มเติมเล็กน้อยในการแสดงความคิดเห็นของ @jedwardsแต่รู้สึกไม่ยืดหยุ่นเท่าวิธีแรกเนื่องจากการเพิ่มช่องหรือการเปลี่ยนลำดับจะทำให้รหัสของเราเสียหาย

public enum Direction {
    NORTH, EAST, SOUTH, WEST;

    // cached values to avoid recreating such array each time method is called
    private static final Direction[] VALUES = values();

    public Direction getOppositeDirection() {
        return VALUES[(ordinal() + 2) % 4]; 
    }
}

3
ฉันกำลังจะ.values()[ordinal()]แฮ็ค แต่วิธีนี้แข็งแกร่งกว่ามาก
jedwards

คุณใช้มันอย่างไร? และเทคนิคนี้เรียกว่าอะไร?
Thufir

1
@Thufir " คุณใช้มันอย่างไร " หากคุณกำลังถามเกี่ยวกับวิธีการเช่นเดียวกับวิธีการอื่น ๆ - คุณเรียกใช้ในอินสแตนซ์ของคลาสด้วยวิธีนี้ กรณีของDirectionชั้น enum มีNORTH, EAST, SOUTH, WESTเพื่อให้คุณสามารถใช้และมันจะกลับมาNORTH.getOppositeDirection() SOUTH" เทคนิคนี้เรียกว่าอะไร " หากคุณกำลังถามstatic{...}ว่ามันเป็นบล็อกการเริ่มต้นแบบคงที่ซึ่งเป็นรหัสที่เรียกใช้เมื่อโหลดคลาสครั้งแรก (เป็นส่วนหนึ่งของกระบวนการเดียวกันกับที่เริ่มต้นฟิลด์แบบคงที่)
Pshemo

@Pshemo ฉันสงสัยว่าโค้ดด้านบนเวอร์ชัน Spring จะเป็นอย่างไรถ้าค่าที่ได้รับการตั้งค่าในบล็อกแบบคงที่จะต้องถูกแทรกจากไฟล์คุณสมบัติพูด
Vikas Prasad

161

สำหรับ enum ขนาดเล็กเช่นนี้ฉันพบทางออกที่อ่านง่ายที่สุดคือ:

public enum Direction {

    NORTH {
        @Override
        public Direction getOppositeDirection() {
            return SOUTH;
        }
    }, 
    SOUTH {
        @Override
        public Direction getOppositeDirection() {
            return NORTH;
        }
    },
    EAST {
        @Override
        public Direction getOppositeDirection() {
            return WEST;
        }
    },
    WEST {
        @Override
        public Direction getOppositeDirection() {
            return EAST;
        }
    };


    public abstract Direction getOppositeDirection();

}

8
ความคิดที่ดี! นอกจากนี้ยังดีเมื่อคุณต้องการให้ค่า enum แต่ละค่ามีพฤติกรรมที่เฉพาะเจาะจง
OferBr

28

ใช้งานได้:

public enum Direction {
    NORTH, SOUTH, EAST, WEST;

    public Direction oppose() {
        switch(this) {
            case NORTH: return SOUTH;
            case SOUTH: return NORTH;
            case EAST:  return WEST;
            case WEST:  return EAST;
        }
        throw new RuntimeException("Case not implemented");
    }
}

8
แทนที่จะส่งคืนค่าว่างเป็นส่วนคำสั่งเริ่มต้นที่พ่น RuntimeException ที่เหมาะสมอาจเป็นการดีกว่าที่จะระบุว่ามีข้อผิดพลาดของโปรแกรมเมอร์ในการไม่กำหนดทิศทางตรงกันข้ามสำหรับทิศทางที่เพิ่มใหม่
Timothy055

1
สิ่งนี้ต้องการให้ผู้โทรจัดการ null นอกจากนี้ยังต้องการผู้ดูแลเพื่อให้แน่ใจว่าพวกเขาเพิ่มเคสทุกครั้งที่มีการเพิ่มประเภททิศทางใหม่ ดูคำตอบของ Amir Afghani เกี่ยวกับการใช้วิธีนามธรรมที่สามารถแทนที่ได้ด้วยค่า enum แต่ละค่าด้วยวิธีนี้คุณจะไม่เสี่ยงต่อการพลาดและคุณไม่ต้องกังวลเกี่ยวกับการจัดการ null
Michael Peterson

14

สร้างวิธีนามธรรมและให้ค่าการแจงนับของคุณลบล้างค่านั้น เนื่องจากคุณรู้สิ่งที่ตรงกันข้ามในขณะที่คุณสร้างมันจึงไม่จำเป็นต้องสร้างหรือสร้างแบบไดนามิก

มันไม่ได้อ่านอย่างสวยงามแม้ว่า; อาจswitchจะจัดการได้มากกว่านี้?

public enum Direction {
    NORTH(1) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.SOUTH;
        }
    },
    SOUTH(-1) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.NORTH;
        }
    },
    EAST(-2) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.WEST;
        }
    },
    WEST(2) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.EAST;
        }
    };

    Direction(int code){
        this.code=code;
    }
    protected int code;

    public int getCode() {
        return this.code;
    }

    public abstract Direction getOppositeDirection();
}

4

ใช่เราทำตลอดเวลา คุณส่งคืนอินสแตนซ์แบบคงที่แทนที่จะเป็นวัตถุใหม่

 static Direction getOppositeDirection(Direction d){
       Direction result = null;
       if (d != null){
           int newCode = -d.getCode();
           for (Direction direction : Direction.values()){
               if (d.getCode() == newCode){
                   result = direction;
               }
           }
       }
       return result;
 }

0
public enum Direction {
    NORTH, EAST, SOUTH, WEST;

    public Direction getOppositeDirection(){
        return Direction.values()[(this.ordinal() + 2) % 4];
    }
}

Enums มีเมธอดค่าคงที่ที่ส่งคืนอาร์เรย์ที่มีค่าทั้งหมดของ enum ตามลำดับที่ประกาศ แหล่ง

ตั้งแต่ NORTH ได้ 1, EAST ได้ 2, SOUTH ได้รับ 3, WEST ได้รับ 4; คุณสามารถสร้างสมการง่ายๆเพื่อให้ได้สมการตรงข้าม:

(มูลค่า + 2)% 4


2
ทำไมถึงเป็นคำตอบ? คุณคาดหวังว่าสิ่งนี้จะช่วยให้ผู้อ่านในอนาคตหรือใครก็ตามในเรื่องนั้นได้เรียนรู้โดยไม่มีคำอธิบายใด ๆ
GrumpyCrouton

แม้ว่ารหัสนี้อาจตอบคำถามได้ แต่การให้บริบทเพิ่มเติมเกี่ยวกับวิธีการและ / หรือเหตุผลในการแก้ปัญหาจะช่วยเพิ่มมูลค่าในระยะยาวของคำตอบ จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตไม่ใช่แค่คนที่ถามตอนนี้! โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายและระบุข้อ จำกัด และสมมติฐานที่ใช้ นอกจากนี้ยังไม่เจ็บที่จะพูดถึงว่าทำไมคำตอบนี้จึงเหมาะสมกว่าข้ออื่น ๆ
ItamarG3

อ่านโค้ดโดยไม่มีความคิดเห็นยากไหม หรือคุณต้องการ javadoc พิเศษสำหรับรหัส 7 บรรทัด?
Pregunton

1
สารละลายนี้มีความเปราะเนื่องจากขึ้นอยู่กับลำดับของค่า enum หากคุณเปลี่ยนลำดับให้เป็นตัวอักษรสมการที่ชาญฉลาดของคุณจะไม่ให้สิ่งที่ตรงกันข้ามอีกต่อไป
Josh J
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.