2010-04-20 20 views
5

Tôi hiện đang phát triển một khung mô phỏng trọng lượng nhẹ, có mục đích chung. Mục đích là để cho phép mọi người phân lớp các đối tượng Mô phỏng và Kịch bản cho các nhu cầu cụ thể theo miền của họ. Generics dường như là một cách thích hợp để đạt được điều này, nhưng tôi sợ rằng tôi có thể nhúng vào địa ngục Generics.Java Generics Hell - Vượt qua điều này nhưng nó muốn gõ T

Đối tượng Sim cung cấp quyền truy cập vào các đối tượng mô phỏng và điều khiển sim (bắt đầu/tạm dừng/dừng)

Đối tượng Scenario cho phép bạn để cư Sim với các thực thể mô phỏng.

Sim:

public class Sim 
{ 
    public <T extends Sim> void loadScenario(Scenario<T> scenario) 
    { 
     reset(); 
     scenario.load(this); 
    } 
} 

Kịch bản:

public interface Scenario<T extends Sim> 
{ 
    public void load(T sim); 
} 

Mục đích là để cho phép người dùng tạo ra một MySim rằng extends SimMyScenario rằng implements Scenario<MySim> cho tên miền của họ.

ví dụ: MyScenario:

public class MyScenario<MySim> 
{ 
    public void load(MySim sim) 
    { 
     // make calls to sim.addMySimEntity(...) 
    } 
} 

Cụ thể, sử dụng đoạn mã trên, các scenario.load(this) cuộc gọi trong Sim.loadScenario mang lại cho tôi những lỗi: Phương pháp tải (T) trong các loại Kịch bản không áp dụng cho các đối số (Sim). Tôi hiểu điều này là bởi vì tôi đang tải this (có loại Sim) khi những gì được yêu cầu là T extends Sim có nghĩa là bằng cách nào đó tôi nên đi qua một đối tượng có thể là bất kỳ loại phụ nào của Sim.

Cách khắc phục vấn đề này để đạt được những gì tôi muốn đạt được là gì? Hoặc, nó thậm chí có thể? Có lẽ generics không thể làm điều này cho tôi.

+0

Tôi nghĩ rằng điều này có thể liên quan đến câu hỏi tôi đã hỏi về tham chiếu chung vòng tròn: http://stackoverflow.com/questions/2567595/creating-circular-generic-references –

Trả lời

6

Nếu nó luôn luôn là một subtype của Sim thì tại sao không chỉ xác định rằng trong phương pháp của bạn và được thực hiện với nó? Nó không có vẻ như generics là mua cho bạn rất nhiều ở đây.

Nhưng dù sao, tôi nghĩ rằng bạn muốn loadScenario là:

public void loadScenario(Scenario<? extends Sim> scenario) 

EDIT: Được rồi bây giờ tôi thực sự nghĩ về nó, điều đó sẽ không làm việc, hoặc. LoadScenario của bạn sẽ chuyển một kịch bản với tham số kiểu T là một kiểu con của Sim. Nhưng bạn đang cố gắng vượt qua nó một Sim mà không có đảm bảo là subtype quyền của Sim.

Giải pháp là phương pháp Scenario.load cần phải mất một Sim tức:

public interface Scenario<T extends Sim> 
{ 
    public void load(Sim sim); 
} 

và Sim vẫn như cách bạn đã viết nó. Lưu ý lớp MySim của bạn phải triển khai thực hiện điều này và khám phá nó thành tham số kiểu của nó.

EDIT: phương pháp khác là sử dụng một phương pháp tĩnh trong lớp cơ sở Sim của bạn:

public class Sim 
{ 
    public static <T extends Sim> void loadScenario(Scenario<T> scenario, T sim) 
    { 
     scenario.load(sim); 
    } 
} 

Nó không phải là tuy nhiên khả năng để làm điều này một phương pháp dụ từ đi qua một thể hiện của Sim tới một cái gì đó kiểu T mở rộng Sim không phải là an toàn. Bằng cách tạo ra một phương thức tĩnh cũng truyền Sim, bạn cung cấp cho trình biên dịch cơ hội để kiểm tra tham số kiểu T cho kịch bản và T cho đối sánh sim.

+0

Chắc chắn bạn có nghĩa là 'tải (T sim)' trong trường hợp cuối cùng? Khác tham số chung trên lớp là ít hơn hữu ích ... :-) –

+0

@Andrzej Không, tôi tin rằng ông có nghĩa là tải (Sim sim). Thật vậy, các generic trên lớp không còn hữu ích nữa. Có vẻ như tôi sẽ không thể hoàn thành những gì tôi muốn làm. – Brad

+0

@Andrzej và @Brad. Đúng, chung chung không phải là hữu ích đó là điểm của phần đầu tiên của bình luận :-) Đa hình bình thường nên có hiệu quả ở đây. –

2

I understand this is because I'm loading this (which is of type Sim) when what is required is T extends Sim which means somehow I should be passing in an object that can be any subtype of Sim.

số Vấn đề là accoding với phương pháp đặc tả, bạn nên đi qua một đối tượng của lớp T, đó là cụ thể lớp con của Sim phù hợp với kịch bản của bạn - mà this không phải là (ít nhất đó mã không thể đảm bảo rằng nó là).

Bạn không chắc chắn cách khắc phục điều này.

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