2013-07-23 31 views
5

Cách tốt nhất để sử dụng lớp này như là lớp cơ sở cho lớp Enum. Tôi muốn có thể tạo các loại bê tông khác nhau mà không cần phải mã hóa lại các phương thức getter.Enum Base Classes trong Java

public enum Tool extends Item 
{ 
    Pickaxe("Pickaxe", 101), 
    Saw("Saw", 201); 
} 

Và Tool.getNames() sẽ trả về danh sách tất cả các tên mục trong lớp Công cụ.

public enum Item 
{ 
    Default("Name", 0); 

    private final int id; 
    private final String name; 

    Item(String name, int id) 
    { 
     this.id = id; 
     this.name = name; 
    } 

    public int getId() 
    { 
     return this.id; 
    } 

    public int[] getIds() 
    { 
     Item[] items = Item.values(); 
     int[] ids = new int[items.length]; 
     for (int i = 0; i < items.length; i++) 
     { 
      ids[i] = items[i].getId(); 
     } 
     return ids; 
    } 

    public String getName() 
    { 
     return this.name; 
    } 

    public String[] getNames() 
    { 
     Item[] items = Item.values(); 
     String[] names = new String[items.length]; 
     for (int i = 0; i < items.length; i++) 
     { 
      names[i] = items[i].getName(); 
     } 
     return names; 
    } 
} 

Tôi biết điều này là không thể, nhưng làm cách nào tôi có thể tiếp cận tình huống này? Tôi muốn có thể truy cập vào các thành viên của mỗi lớp giống như bạn sẽ là một enum: Tool.Pickaxe.

+3

Một gợi ý: enums không thể mở rộng lớp khác, tuy nhiên chúng vẫn có thể triển khai giao diện. – skiwi

+1

Enums tự động mở rộng lớp 'Enum'. Họ không thể mở rộng một lớp học. Sử dụng giao diện. – MathSquared

+0

Thực hiện một giao diện có nghĩa là tôi sẽ vẫn phải mã hóa các phương thức cho mỗi lớp con. Tôi muốn tránh điều này bằng cách nào đó. –

Trả lời

4

Bạn sẽ phải tự mình triển khai, bạn không thể mở rộng hành vi đã được triển khai. Tuy nhiên bạn có thể buộc chính mình, hoặc bất cứ ai khác, để thực hiện các phương pháp khác nhau:

public interface Item { 
    public int getId(); 
    public String getName(); 
} 

public enum Tool implements Item { 
    Pickaxe("Pickaxe", 101), 
    Saw("Saw", 201); 

    private final int id; 
    private final String name; 

    public Item(final String name, final int id) { 
     this.id = id; 
     this.name = name; 
    } 

    @Override 
    public int getId() { 
     return id; 
    } 

    @Override 
    public String getName() { 
     return name; 
    } 
} 

Đó là phần một, bây giờ bạn không muốn truy cập getIds()getNames() qua một enum 'dụ' bản thân , nhưng bạn muốn truy cập chúng thông qua lớp như một hàm tĩnh.

Tôi hy vọng điều này sẽ giúp bạn đủ, nhưng nó hoàn toàn xa vời và với generics thậm chí có thể có cách để làm điều đó đơn giản hơn, nhưng hiểu rằng enums không thể mở rộng bất cứ điều gì.

1

Bạn có thể tham gia một phần.

public class MyItem extends Item<MyItem.Items> { 
    public MyItem() { 
    // Tell my parent class about my enum. 
    super(EnumSet.allOf(Items.class)); 
    } 
    public enum Items implements Item.Items { 
    Pickaxe("Pickaxe", 101), 
    Saw("Saw", 201); 
    private final int id; 
    private final String name; 

    // You have to do these. 
    Items(String name, int id) { 
     this.id = id; 
     this.name = name; 
    } 

    @Override 
    public int getId() { 
     return this.id; 
    } 

    @Override 
    public String getName() { 
     return this.name; 
    } 

    } 
} 

// The parent class that does the common work. 
public class Item<I extends Enum<I> & Item.Items> { 
    // Keep track of the items. 
    private final Set<I> items; 

    // Pas a set of the items in the constructor. 
    public Item(Set<I> items) { 
    this.items = items; 
    } 

    // The interface. 
    public interface Items { 
    public int getId(); 

    public String getName(); 

    } 

    // Ready-made functionality. 
    public List<Integer> getIds() { 
    List<Integer> ids = new ArrayList<>(); 
    for (I i : items) { 
     ids.add(i.getId()); 
    } 
    return ids; 
    } 

    public List<String> getNames() { 
    List<String> names = new ArrayList<>(); 
    for (I i : items) { 
     names.add(i.getName()); 
    } 
    return names; 
    } 

} 

Ở đây bạn vẫn phải có người xây dựng enum lưu trữ các trường nhưng bạn chỉ cần triển khai giao diện. Lớp cha sau đó có thể thực hiện tất cả các công việc trên một Set nó được đưa ra tại thời gian xây dựng.

Bạn chắc chắn có thể sử dụng kỹ thuật này để di chuyển nhiều mã ra khỏi lớp cha nhưng đáng tiếc không phải tất cả.