2010-08-06 41 views
5

Tôi đang nghiên cứu vật lý thiên văn. Tôi đã viết một gói chứa các lớp Star, Band và Datfile. Tôi cũng có kiểu BandName được liệt kê. Mỗi ngôi sao chứa một vài Bands, mỗi Band chứa một vài Datfiles.Thừa kế liệt kê trong Java?

Tôi có dữ liệu quan sát cho một số thiên hà. Đối với mỗi cái, tôi tạo một lớp StarDatabase (một HashMap of Stars) và một lớp Main.

Sự cố tôi gặp phải là với loại BandName được liệt kê. Cho đến nay, tất cả các dữ liệu tôi đã sử dụng đã nằm trong các ban nhạc I và V. Bây giờ tôi có dữ liệu trong các băng tần J, H và K. Nếu tôi chỉ cần thêm J, H, và K vào BandName, tất cả các vòng lặp của tôi lặp qua tất cả các mục trong BandName và làm một cái gì đó đang bị hỏng.

Bất kỳ ý tưởng nào?

Chỉnh sửa: Để tổng hợp vấn đề của tôi, tôi muốn mọi gói có tên BandName riêng mà nó có thể lặp qua. Nhưng điều này không làm việc, bởi vì các phương thức trong gói Star đang chờ các đối tượng kiểu Star.BandName và tôi đang cung cấp các đối tượng kiểu IndividualPackage.BandName.

+0

Tại sao bạn lặp lại qua BandNames? – ILMTitan

+0

Trong trường hợp một Ban nhạc mới cần phải được thêm vào, ở khắp mọi nơi mà tôi sử dụng một BandName sẽ không cần phải được cập nhật. – rhombidodecahedron

+0

Các gói tương ứng với những gì? Đó là, tại sao bạn phân lớp các lớp này ở nơi đầu tiên? –

Trả lời

18

Bạn không thể kế thừa một enum từ một enum khác, mặc dù bạn có thể có enum của bạn thực hiện một giao diện. Các vấn đề kỹ thuật (mà tất cả enums ngầm mở rộng java.lang.Enum, do đó họ không thể mở rộng lớp khác, chỉ thực hiện các giao diện bổ sung) là không phải ngẫu nhiên:

Đối với hầu hết các phần, khả năng mở rộng của enums hóa ra là một xấu ý kiến. Điều gây nhầm lẫn là các phần tử của loại tiện ích mở rộng là trường hợp của loại cơ sở và không ngược lại. Không có cách nào tốt để liệt kê tất cả các phần tử của loại cơ sở và phần mở rộng của nó. Cuối cùng, khả năng mở rộng sẽ làm phức tạp nhiều khía cạnh của thiết kế và triển khai.

Từ Effective Java 2nd Edition khoản 34.

Tuy nhiên, tôi không hoàn toàn hiểu được vấn đề của bạn: chưa bạn sử dụng values() cho iterating qua enum của bạn? Sau đó, bạn không nên lo lắng về việc mở rộng enum của bạn với các giá trị mới.

Hãy chỉ định rõ ràng hơn những gì "hỏng" được cho là có ý nghĩa.

Cập nhật: vì vậy bạn cần phải có bộ riêng biệt của ban nhạc với nhiều loại khác nhau của các ngôi sao - điều này có thể được thực hiện bằng sự đếm riêng biệt mở rộng một giao diện chung, ví dụ:

interface Band { 
    String getName(); 
    void doStuff(); 
    ... 
} 

enum BandsVI implements Band { 
    V, I; 
    public String getName() { return toString(); } 
    public void doStuff() { /* do stuff as appropriate for these bands */ } 
    ... 
} 

enum BandsJHK implements Band { 
    J, H, K; 
    public String getName() { return toString(); } 
    public void doStuff() { /* do stuff as appropriate for these bands */ } 
    ... 
} 

Và bạn có thể sử dụng các bằng làm cho lớp Ngôi sao chung chung của bạn:

class Star<T extends Enum<T> & Band> { 
    private Class<T> bandType; 
    public Star(Class<T> bandType) { this.bandType = bandType; } 
    public void printBandNames() { 
    for (Band b : bandType.getEnumConstants()) 
     System.out.println(b.getName()); 
    } 
    public void doStuffOnAllBands() { 
    for (Band b : bandType.getEnumConstants()) 
     b.doStuff(); 
    } 
} 
... 
Star<BandsVI> star1 = new Star<BandsVI>(BandsVI.class); 
Star<BandsJHK> star2 = new Star<BandsJHK>(BandsJHK.class); 
star1.printBandNames(); // prints V I 
star2.printBandNames(); // prints J H K 

Điều này hoạt động tốt nếu các nhóm được tổ chức thành các nhóm riêng biệt. Nếu có những ngôi sao với các nhóm nhạc hỗn hợp, tuy nhiên, bạn có thể thích một cách tiếp cận khác:

class Star { 
    private List<? extends Band> bandTypes; 
    public Star(List<? extends Band> bandTypes) { this.bandTypes = bandTypes; } 
    public void printBandNames() { 
    for (Band b : bandTypes) 
     System.out.println(b.getName()); 
    } 
    ... 
} 

... 
Star star1 = new Star(Arrays.asList(BandsVI.values())); 
Star star3 = new Star(Arrays.asList(new Band[]{BandsVI.V, BandsVI.I, BandsJHK.K})); 
... 

này cho phép bạn thiết lập sao với một sự pha trộn độc đoán của ban nhạc. Tuy nhiên, theo cách này, bạn không thể sử dụng EnumSet hoặc EnumMap trên các băng tần.

+0

Ví dụ, mỗi đối tượng Sao lặp qua BandName.values ​​() và thêm một Băng mới với giá trị được đặt tên. Sau đó, Ban nhạc đó tìm trong thư mục/giá trị để lấy các tệp dữ liệu. Sau đó, GUI làm cho một BandRadioButton mới ra khỏi mỗi Band trong BandName.values ​​() ... vv và vân vân. – rhombidodecahedron

+0

@Earl, tôi vẫn không nhận được nơi mà vấn đề nằm: là datfile cho các ban nhạc mới mất tích, hoặc không giao diện có được điều sai lầm, hoặc ...? –

+0

GUI thực sự bị rối tung lên. Các ngôi sao quan tâm đến các băng tần V và I không nên tương tác với J, H hoặc K. Tôi muốn nó lặp qua các giá trị (thay vì đặt tên chúng một cách rõ ràng) trong trường hợp cần thêm một ban nhạc mới _does_. – rhombidodecahedron

0

Tất cả các enums ngầm mở rộng java.lang.Enum. Vì Java không hỗ trợ đa thừa kế một enum không thể mở rộng bất cứ thứ gì khác.- http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

+0

Tôi biết điều này. Do đó câu hỏi. – rhombidodecahedron

+2

@Earl, anh không có cách nào để biết bạn biết điều này. Rất khó để chúng tôi có thể cung cấp cho bạn câu trả lời hay nếu bạn không cung cấp cho chúng tôi đủ thông tin về vấn đề này. –

+0

Tôi xin lỗi. Đó không phải là âm mưu thô lỗ. – rhombidodecahedron

0

Đây là những gì tôi muốn làm (pseudo-code):

class Band 
{ 
    String name; 
}; 
static Band J("J"); 
static Band K("K"); 

static ArrayList<Band> JK; 
static ArrayList<Band> IHL; 

class Star 
{ 
    Star(ArrayList<Band> bands) 
} 

Bằng cách này bạn có thể thêm các ban nhạc chỉ bằng cách tạo ra nhiều đối tượng Band. Mỗi lần bắt đầu có danh sách các dải mà nó sử dụng để nó có thể lặp qua tất cả chúng.