2012-09-27 48 views
6

Câu hỏi của tôi có thể là rất đơn giản,Java: Đối với mỗi vòng lặp, các đối tượng lặp lại qua mở rộng

Tôi có một lớp Result với một số lĩnh vực bên trong, setters và thu khí.

Ngoài ra, tôi có lớp Special1Result mở rộng Result và bao gồm một số trường khác và Special2Result bằng một số dữ liệu khác.

Trong lớp khác nhau Dispatcher, tôi đã viết các phương pháp sau đây:

processResults(List<? extends Result> results), mà chỉ quen thuộc với Result (Tôi cần phương pháp này để truy vấn nếu có lĩnh vực cụ thể trong đối tượng Kết quả mở rộng - Tôi đang sử dụng chú thích).

Vì vậy, tôi đã quyết định sử dụng mở rộng cho-mỗi vòng lặp: for (Result res : results) {}

Vì vậy, câu hỏi của tôi là gì? tôi đang cố gắng tìm kiếm trên web cách viết này cho vòng lặp cho các đối tượng mở rộng, ví dụ: một cái gì đó như thế này for (? extends Results res: results){}

Có thể không? Làm thế nào là cách chính xác để viết nó?

Trả lời

2

Tôi đang cố tìm trên web cách viết vòng lặp này cho các đối tượng mở rộng, ví dụ: một cái gì đó như thế này

for (? extends Results res: results){} 

Không, đây là không thể: bạn có thể không tĩnh gõ mục cung cấp tự động tại thời gian chạy.

Cách viết chính xác?

Bạn đã làm việc đó:

for (Results res: results) { 
} 

Nếu bạn muốn thử nghiệm cho Special2Result bên trong vòng lặp đó, bạn có thể làm điều đó, nhưng thường nó nói rằng thiết kế của bạn có thể được cải thiện. Một lựa chọn tốt hơn là sử dụng một cơ chế của công văn kép, chẳng hạn như Visitor Pattern, để ẩn các chi tiết về điều trị đặc biệt cho các lớp con của bạn.

+1

+1 Cảm ơn, tôi sẽ kiểm tra cách tôi có thể sử dụng Mẫu khách truy cập đây. – Michael

+0

+1 cho Mẫu khách truy cập. – EthanB

5

Tất cả những gì bạn biết về một List<? extends Result> là mỗi phần tử sẽ là Result - vì vậy đó là tất cả những gì bạn có thể đặt vào cú pháp tăng cường cho vòng lặp.

Nếu bạn cần các thành viên mà không được khai báo trong Result, bạn sẽ cần phải cast bên trong vòng lặp:

for (Result result : results) { 
    if (result instanceof CleverResult) { 
     CleverResult clever = (CleverResult) result; 
     // Use clever here 
    } 
} 

Hãy suy nghĩ về những gì bạn muốn viết nếu bạn không sử dụng một nâng cao cho vòng lặp - bạn vẫn cần phải viết diễn viên, phải không?

Tất nhiên, nếu bạn biết rằng danh sách nên thực sự chỉ chứa một loại cụ thể, bạn luôn có thể truyền vô điều kiện trong vòng lặp.

+0

+1, Cảm ơn bạn, mặc dù tôi không thể yêu cầu instanceof là gì, vì tôi không biết các loại khác nhau của kết quả đặc biệt trong điều phối class – Michael

+0

@Michael: Sau đó, bạn không thể sử dụng một cách hợp lý sự khác biệt đó, vì vậy nó sẽ không thành vấn đề, phải không? Tại sao bạn * muốn * có một biến kiểu mà bạn không thể dự đoán? –

+0

nó được sử dụng thường xuyên khi bạn lập trình với một nhóm từ xa, một người chịu trách nhiệm về khuôn khổ và cho phép bạn mở rộng các đối tượng của họ miễn là bạn sử dụng định dạng được xác định trước, bằng cách sử dụng chú thích chẳng hạn. Các sản phẩm tôi đang làm việc thực hiện thiết kế này, và tôi muốn mở rộng nó một chút. Sử dụng chú thích (@interface), bạn có thể chỉ ra cho người dùng lớp siêu trường nào quan trọng, loại nào sẽ được kiểm tra và nhiều hơn nữa ... nhà thiết kế khung vẫn cần có khả năng xử lý đối tượng mở rộng bởi các nhà phát triển khác nhau mà không biết thực hiện. – Michael

1

Java có kiểu xóa - các tham số kiểu cụ thể của các bộ sưu tập không có trong thời gian chạy.

Vì vậy, nếu bạn có Danh sách, trình biên dịch java sẽ đảm bảo rằng không có mã nào sẽ đưa bất kỳ thứ gì vào danh sách không phải là một phân lớp của Kết quả. Theo đó, trong thời gian chạy, tất cả các vòng lặp của bạn có thể biết là nội dung là tất cả các lớp con của Kết quả - vì vậy cách duy nhất để lặp qua chúng là một tập hợp các tham chiếu đến Result. kết quả của bất kỳ lớp con nào có trong danh sách.

+0

+1, cảm ơn, tôi mặc dù trong quá khứ rằng nếu bạn đúc một đối tượng mở rộng lớn hơn đến một đối tượng siêu lớp nhỏ hơn, bạn có thể mất một số tính năng trong lớp – Michael

1

Vì lớp con cụ thể của bạn chỉ khác nhau theo bản chất của các trường, tôi khuyên bạn nên hưởng lợi từ tính đa hình đơn giản.

Bạn sẽ kết thúc với lớp giao diện Result/abstract xác định lớp phương thức execute() được thực hiện bởi nhiều lớp hoặc lớp con khi bạn cần có hành động tự thực hiện.

Do đó, mã khách hàng của bạn chỉ có thể sử dụng:

for (Result res : results){ //results being as a List<Result> type 
    res.execute(); 
} 
+0

+1, Cảm ơn, tôi sẽ kiểm tra xem thực thi có phải là một tùy chọn hay không. – Michael

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