2010-03-19 34 views
12

Có thể (hoặc thậm chí được khuyến nghị) để đúc phần tử được lấy từ một cho mỗi câu lệnh trong chính câu lệnh đó không? Tôi biết rằng mỗi phần tử trong danh sách sẽ thuộc loại <SubType>.Phần tử truyền trong Java Đối với mỗi câu lệnh

tức là .:

List<BaseType> list = DAO.getList(); 
for(<SubType> element : list){ 
    // Cannot convert from element type <BaseType> to <SubType> 
    ... 
} 

hơn:

List <BaseType> list = DAO.getList(); 
for(<BaseType> el : list){ 
    <SubType> element = (<SubType>)el; 
    ... 
} 

Trả lời

12

Bạn thực sự biết rằng mỗi mục sẽ là một subtype? DAO chỉ đơn giản là phải hoàn thành hợp đồng List<BaseType> và nếu bạn giả định một lớp con, thì tôi nghĩ có điều gì đó sai ở đâu đó. Tôi có lẽ sẽ tập trung nhiều hơn vào việc đưa giao diện vào DAO chính xác, và có nó trả về hợp đồng những gì bạn muốn.

+0

+1 để nêu rõ cơ chế hợp đồng mà giao diện phải tuân thủ. – aperkins

+1

Thật không may mã DAO không phải là của chúng tôi. Tuy nhiên, nguồn cấp dữ liệu vào nguồn dữ liệu là. Chúng tôi phân lớp (chỉ có phân lớp đó) vì chúng tôi muốn có thêm chức năng trong lớp. Vì chúng tôi kiểm soát đầu vào và chúng tôi chỉ đặt các đối tượng trong đó tôi cảm thấy tôi có thể khá chắc chắn rằng đối tượng đã truy xuất sẽ thực sự là một trong số . Nếu chúng tôi kiểm soát tất cả mã, bạn sẽ chính xác 100%. –

+3

@Carl - có đáng để gói DAO sau đó không và cung cấp giao diện * khác * để thực hiện những gì bạn muốn. Nếu không, bạn sẽ phải chuyển đổi tất cả trên cơ sở mã của bạn (có khả năng - tôi nhận ra tôi đang đưa ra giả định về cách phân phối rộng rãi này) –

1

Có thể, có! nhưng thần cấm, Tại sao? Những nỗ lực ban đầu của tôi trong sự nghiệp của tôi đã làm điều đó và tôi đã học được. Lập trình cho giao diện luôn có lợi thế. Tôi luôn nhận được câu hỏi từ các nhà phát triển cơ sở về việc xử lý các trường hợp chỉ có các kiểu con có các phương thức/chức năng được yêu cầu.

Nói Lớp học động vật với loại con chó có phương thức bark(). Họ muốn hàm bark(). Thách thức thực tế là họ muốn có một hành vi của giao tiếp động vật không sủa() nhưng động vật nói(). Vì vậy, một lớp con mèo mới sẽ không yêu cầu meow(). Điều gì về điều này sau đó: - Con chó của tôi hình thành một gói, nhưng con mèo thì không. Hành vi của gói trả lời() không thuộc sở hữu của một con chó duy nhất. Gói là một khía cạnh khác, chuyển gói cho tất cả các đối tượng và yêu cầu các đối tượng tham gia gói. (Mẫu khách truy cập/Mẫu bộ điều hợp). Lớp sói của tôi có thể sử dụng cùng một hành vi.

Tôi có cứng nhắc về điều này không, nếu nó chỉ là 1 tắt dụ tôi ổn. Nếu câu trả lời là tôi không chắc chắn, thì bạn nên chơi an toàn hơn bằng cách làm việc tại các hợp đồng giao diện.

12

Vì tất cả các lý do được nêu bởi những người khác, bạn không nên làm điều này. Tuy nhiên, nếu bạn không thể thay đổi giao diện, sau đây là có thể:

for (BaseType element : list) { 
    SubType subType = (SubType)element; 
    ... 
} 

Theo như tôi biết, đây là cách duy nhất để làm điều này và vẫn thực sự là loại an toàn - tức là không phụ thuộc vào loại tẩy xoá để đón bất kỳ vấn đề, mà nó sẽ không nhất thiết phải làm cho đến sau này.

Tôi nhận thấy đây không phải là chính xác những gì bạn đang tìm kiếm, nhưng nó xử lý việc truyền.

+0

Tôi nên lưu ý, nếu bạn CÓ THỂ thay đổi giao diện, và nó sẽ luôn là SubType, bạn NÊN thay đổi giao diện, cho dù đó là thông qua một phần mở rộng phân lớp hoặc chỉ thay đổi nó. – aperkins

+2

Để thực sự an toàn, bạn có thể làm: nếu (phần tử instanceof SubType) – VolatileDream

+0

Rất đúng - tôi nên đặt nó. – aperkins

0

Nếu bạn không thuộc bộ sưu tập của Google, bạn có thể bọc danh sách với phương thức transform. Trong trường hợp của bạn, nó sẽ rất hiệu quả và hoàn toàn tuân thủ. Tôi sẽ đặt nó như một phương pháp bao bọc mặc dù Brian đã gợi ý.

public List<SubType> fromDao () 
{ 
    // Put a comment for maintainer 

    // Lists from DAO always contain SubTypes 
    return 
     Lists.transform(
      DAO.getList(), 
      new Function< BaseType, SubType >() 
      { 
       public SubType apply (final BaseType from) 
       { 
        return (SybType) from; 
       } 
      }; 
} 
9

Đó là trong thực tế có thể kết hợp các diễn viên với vòng for, như vậy:

List<BaseType> list = DAO.getList(); 
for (SubType subType : ((List<SubType>) list)){ 
    ... 
} 

Hoặc bạn có thể sử dụng mô hình hơi-sạch:

List<SubType> list = (List<SubType>) DAO.getList(); 
for (SubType subType : list){ 
    ... 
} 

Bạn sẽ nhận được một cảnh báo cast được bỏ chọn từ trình biên dịch Java, trừ khi bạn bỏ nó. Hiệu ứng của mẫu đầu tiên sẽ có hiệu quả giống nhau khi đúc từng phần tử trong vòng lặp. Biểu mẫu thứ hai cũng sẽ thực thi các bổ sung mới vào danh sách phải phù hợp với SubType.

Lưu ý rằng điều này sẽ KHÔNG hoạt động với các mảng, vì các mảng có các kiểu thời gian chạy riêng biệt. Nói cách khác, BaseType [] không thể chuyển thành SubType []. Bạn có thể sử dụng API mảng để giải quyết vấn đề này, như vậy:

BaseType[] array = DAO.getArray(); 
for (SubType subType : Arrays.<SubType>asList(array)) { 
    ... 
} 
+0

Những phôi không hợp pháp, mặc dù bạn có thể làm [một số thủ thuật] (https://stackoverflow.com/questions/933447/how-do-you-cast-a-list-of-objects-from-one-type- to-another-in-java) để làm việc xung quanh nó (giống như một dàn diễn viên trung gian cho 'Danh sách '.) [java tutorial] (https://docs.oracle.com/javase/tutorial/java/generics/subtyping. html) được liên kết từ ghi chú câu hỏi đó: "Mặc dù Số nguyên là một loại phụ của Số, Danh sách không phải là loại phụ của Danh sách và, trên thực tế, hai loại này không liên quan. . " –

+0

Ví dụ thứ hai sẽ hoạt động nếu DAO.getList trả về một Danh sách không được định dạng thay vì Danh sách . Mẫu có thể hữu ích khi xử lý một codebase cũ mà không có bộ sưu tập nào được nhập. – harperska

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