2012-04-02 60 views
6

Hãy xem xét ví dụ đơn giản dưới đây về việc triển khai một phương thức trong một Enum. Một vấn đề với phương pháp này là, khi bạn có rất nhiều trường hợp enum, bạn trực quan không còn có thể nhìn thấy tất cả cùng một lúc, như một danh sách. Đó là, nếu chúng tôi có nhiều đồ chơi, tôi muốn xem "DOLL, SOLDIER, TEDDYBEAR, TRAIN, ETC", cùng nhau, trong một danh sách dài và sau đó tôi có thể triển khai bất kỳ phương pháp cần thiết nào, ví dụ: các phương thức trừu tượng trong chính enum.Java Enums: Phương thức triển khai sau khi khai báo?

Có cách nào để thực hiện việc này không? Hay bạn phải thực hiện các phương thức khi bạn khai báo các cá thể enum riêng lẻ, như trong ví dụ dưới đây?

public enum Toy { 
    DOLL() { 
      @Override public void execute() { 
       System.out.println("I'm a doll."); 
      } 
    }, 
    SOLDIER() { 
      @Override public void execute() { 
       System.out.println("I'm a soldier."); 
      } 
    }; 
    //abstract method 
    public abstract void execute(); 
} 
+1

Cách bạn làm điều này ở trên là cách _preferred_ để làm điều đó, FYI. –

+0

Ý của bạn là gì? Theo nguồn nào? – Jonah

+0

Theo Java hiệu quả. –

Trả lời

5

Một cách mà nói đến cái tâm là để lại việc thực hiện các phương pháp trừu tượng để tách các lớp thực hiện, một cái gì đó như:

interface ToyBehaviour { 

    void execute(); 
} 

public enum Toy { 
    DOLL(new DollBehaviour()), 
    SOLDIER(new SoldierBehaviour()); 

    private final ToyBehaviour behaviour;  

    Toy(ToyBehaviour impl) { 

     behaviour = impl; 
    } 

    public void execute() { 

     behaviour.execute(); 
    } 
} 

class DollBehaviour implements ToyBehaviour { 

    public void execute() { 
     System.out.println("I'm a doll."); 
    } 
} 

Thiết lập này sẽ cho phép bạn tạo các lớp hành vi trong các tập tin riêng biệt trong trường hợp đó thực hiện của bạn có đủ phức tạp để đảm bảo sự tách biệt.

Trong trường hợp việc thực hiện đơn giản là đủ để đưa nó vào một enum lớp, bạn có thể đặt các lớp giao diện và hành vi như con của lớp enum:

public enum Toy { 
    // enum values 
    DOLL(new DollBehaviour()), 
    SOLDIER(new SoldierBehaviour()); 

    private final ToyBehaviour behaviour;  

    Toy(ToyBehaviour impl) { 

     behaviour = impl; 
    } 

    public void execute() { 

     behaviour.execute(); 
    } 

    // behaviour interface 
    interface ToyBehaviour { 

     void execute(); 
    } 

    // behaviour implementation (sub)classes 
    static class DollBehaviour implements ToyBehaviour { 

     public void execute() { 
      System.out.println("I'm a doll."); 
     } 
    } 

    // etc ... 
} 

tôi có lẽ sẽ lựa chọn cho đầu tiên thực hiện bản thân mình, trừ khi hệ thống phân cấp của các lớp thực hiện là rất tầm thường.

4

Nếu bạn muốn khai báo enum nhỏ gọn hơn, cách duy nhất tôi có thể nghĩ ra để làm điều đó là:

nếu bạn có thể xây dựng các phương pháp của bạn ra khỏi biến initializer:

public enum Toy { 
    DOLL("doll"),SOLDIER("soldier"); 

    private Toy(String name){ this.name=name;} 
    public void execute(){ System.out.println("I'm a "+name);} 
} 

hoặc , hơi phức tạp hơn, tương tự với các chức năng, nếu hành vi phức tạp hơn -

abstract class SomeToyMethod { 
    abstract void execute(); 

    public SomeToyMethod DOLL_METHOD = new SomeToyMethod(){ 
    public void execute(){ System.out.println("I'm a doll");}) 
    public SomeToyMethod SOLDIER_METHOD = new SomeToyMethod(){ 
    public void execute(){ System.out.println("I'm a soldier");}) 


public enum Toy { 
    DOLL(SomeToyMethod,DOLL_METHOD),SOLDIER(SomeToyMethod.SOLDIER_METHOD); 

    private Toy(SomeToyMethod method){ this.method=method;} 
    public void execute(){ method.execute();} 
} 
+1

'Bạn không thể khai báo các phương pháp trừu tượng trong enums'. Không đúng. – darrengorman

+0

Ah, bạn đúng - trình biên dịch của tôi thực sự nói rằng chỉ được phép nếu bạn khai báo các enums thực hiện phương thức trừu tượng. Cảm ơn bạn đã sửa, sẽ sửa lại phần trên. –

+0

Phương pháp trừu tượng trong enums là hoàn toàn hợp pháp. – Yanflea

2

Bạn có thể thử một cái gì đó như:

public enum Toy { 
    DOLL, 
    SOLDIER, 
    ANOTHER_TOY; 

    public static void execute(Toy toy) { 
     switch(toy) { 
      case DOLL: 
       System.out.println("I'm a doll."); 
       break; 
      case SOLDIER: 
       System.out.println("I'm a soldier."); 
       break; 
      case ANOTHER_TOY: 
       System.out.println("I'm another toy."); 
       break; 
     } 
    } 
} 

Không rất đẹp nhưng nó giữ tờ khai enum của bạn với nhau.

+0

sữa, funny, tôi thực sự nghĩ về điều đó, và cho sự đơn giản của hành vi mẫu của tôi nó sẽ làm việc tốt, nhưng điều này sẽ không cho tôi một hit hiệu suất? Tôi sẽ sử dụng các enums này trong bối cảnh mô phỏng (hàng triệu lượt truy cập), vì vậy tôi nghĩ rằng các trường hợp "tra cứu" sẽ làm chậm chương trình xuống một chút ... bạn nghĩ sao? – Jonah

+0

Lưu ý rằng điều này có hiệu quả loại bỏ sự đóng gói/đa hình được cung cấp bởi bản gốc. –

+1

Lưu ý, bạn có thể xóa tĩnh và tham số, rồi bật 'this'. Báo cáo trường hợp rất nhanh. Tôi thích làm điều này, nhưng chỉ khi chuyển đổi được xác định trong enum chính nó, và chỉ khi các tùy chọn khác nhau là một lớp lót. – ILMTitan

Các vấn đề liên quan