2016-02-24 19 views
6

Tôi đang sử dụng một thùng chứa không đồng nhất tương tự như this one. Tôi có thể đặt và nhận các vật thể từ thùng chứa một cách dễ dàng:Lặp lại trên thùng chứa không đồng nhất

Favorites f = new Favorites(); 
f.putFavorite(String.class, "Java"); 
String someString = f.getFavorite(String.class); 

Nhưng dường như không có cách nào dễ dàng để lặp qua vùng chứa đó. Tôi có thể thêm một phương pháp keySet() đến lớp Favorites và chỉ đơn giản là trả lại bộ chủ chốt của Map đối tượng bên trong:

public Set<Class<?>> keySet() { 
    return favorites.keySet(); 
} 

Bây giờ, tôi muốn để lặp qua các phím, sử dụng các phím để có được các giá trị liên quan, và gọi một số phương pháp trên các đối tượng nhận:

for (Class<?> klass : f.keySet()) { 
    // f.getFavorite(klass).<SOME_METHOD_SPECIFIC_TO_THE_CLASS-KEY> 
} 

tôi nghĩ rằng tôi có thể truy cập vào các phương pháp của các đối tượng tổ chức tại container của tôi bằng cách gọi klass.cast(f.getFavorite(klass)).SOME_METHOD(), nhưng nó không hoạt động hoặc (có nghĩa là, tôi không thể truy cập vào bất kỳ phương pháp trừ cho các phương pháp có liên quan Object).

Giả sử, trong trường hợp sử dụng của tôi, tôi muốn kiểm tra các giao diện của tất cả các đối tượng này mà tôi lặp lại và hành động phù hợp với giao diện được phát hiện. Cũng giả sử rằng tôi có thể có hàng tá đối tượng của các lớp khác nhau và tất cả chúng đều thực hiện một trong ba giao diện.

Giải pháp duy nhất tôi có thể nghĩ là xếp mã của mình bằng hàng chục séc isinstance, nhưng tôi thích cách tiếp cận ít cồng kềnh hơn (ví dụ: kiểm tra xem một đối tượng cụ thể có thực hiện một trong ba giao diện) không.

+0

Bạn có một ý tưởng về "cách tiếp cận ít cồng kềnh" mà bạn đang hình dung? Ý tôi là nếu bạn có ba phần mã khác nhau mà bạn muốn chạy tùy thuộc vào việc nó có thực hiện một trong ba giao diện khác nhau hay không, có vẻ như cách tiếp cận chúng ta có thể đề xuất sẽ có ba nhánh khác nhau. Vì vậy, nó sẽ là tốt để có sự rõ ràng về những gì chính xác bạn đang tìm cồng kềnh. –

+0

Xin lỗi, có thể tôi chưa đủ rõ ràng. Tôi xem xét việc "kiểm tra nếu một đối tượng nhất định thực hiện một trong ba giao diện" tiếp cận được ít cồng kềnh. Ít nhất là khi so sánh với kịch bản với hàng chục câu lệnh "if". –

+0

Tôi không chắc chúng ta sẽ đi đâu từ 3 câu lệnh đến hàng chục ... câu trả lời của tôi sẽ sử dụng 3 câu lệnh if, đó là những gì bạn đang tìm kiếm? Vấn đề với việc kiểm tra ba giao diện cùng một lúc là bạn đang đi sau đó cần phải làm một cái gì đó khác nhau tùy thuộc vào đó của giao diện ba nó phù hợp anyway, vì vậy những gì nó có được bạn? –

Trả lời

5

Bằng cách cố gắng gọi một phương thức cụ thể trên mỗi mục, về cơ bản bạn nói rằng bạn biết rõ hơn trình biên dịch và bạn biết mỗi mục có một lớp siêu cụ thể.

Nếu bạn biết đó là trường hợp, bạn có thể sử dụng Class#asSubclassklass như Class<? extends KnownSuper> để getFavorite sau đó sẽ trở lại một lớp con của KnownSuper (và do đó tiếp xúc với phương pháp):

Class<KnownSuper> superClass = KnownSuper.class; //class with callMethod() 
for (Class<?> klass : f.keySet()) { 
    f.getFavorite(klass.asSubClass(superClass)).callMethod() 
} 

Tuy nhiên, điều này sẽ rõ ràng cung cấp ngoại lệ thời gian chạy nếu một trong các lớp chính không mở rộng KnownSuper. Vì vậy, nếu ở trên sẽ an toàn, bạn nên tham số hóa container không đồng nhất của bạn để chỉ chấp nhận các lớp chính mở rộng từ KnownSuper ở nơi đầu tiên.

Nếu không phải tất cả các mục sẽ thể loại này, bạn cũng có thể kiểm tra đầu tiên nếu phím là phù hợp khi lặp lại:

Class<KnownSuper> superClass = KnownSuper.class; //class with callMethod() 
for (Class<?> klass : f.keySet()) { 
    if (superClass.isAssignableFrom(klass)) { 
     f.getFavorite(klass.asSubClass(superClass)).callMethod() 
    } 
} 
0

Chỉ cần đi qua ví dụ này đơn giản

Giả sử bạn có dưới đây Favorites định nghĩa lớp

public class Favorites extends HashMap<String, String> { 

} 

Đây là lớp thử nghiệm

public class TestGeneric { 

    public static void main(String[] args) { 

     Favorites f = new Favorites(); 
     f.put("test", "test"); 

     for (String test1 : f.keySet()) { 

      f.get("").charAt(index)// you will see all string specific method as compiler knows in advance what object map going to contain 


    } 

} 

Thời điểm bạn thay đổi Favorites extends HashMap<String, String> để Favorites extends HashMap bạn sẽ chỉ phản đối phương pháp cụ thể như trình biên dịch không biết trước mà đối tượng yêu thích đang xảy ra để đưa vào bản đồ

+1

Điểm sử dụng ** thùng chứa ** không đồng nhất là có thể đặt ** đối tượng ** không đồng nhất vào trong đó. Ví dụ: 'f.putFavorite (String.class," Java "); f.putFavorite (Integer.class, 1); '. –

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