2009-03-06 48 views

Trả lời

16

Không có sự khác biệt thực tế về những gì bạn có thể làm khi bạn có một trong số chúng, vì thông số loại chỉ được sử dụng ở vị trí "đầu ra". Mặt khác, có một sự khác biệt lớn về những gì bạn có thể sử dụng một trong số đó.

Giả sử bạn có một số Enumeration<JarEntry> - bạn không thể chuyển điều này đến phương thức lấy Enumeration<ZipEntry> làm một trong các đối số của nó. Tuy nhiên, bạn có thể chuyển nó sang phương thức lấy Enumeration<? extends ZipEntry>.

Điều thú vị hơn khi bạn có loại sử dụng thông số loại ở cả vị trí đầu vào và đầu ra - List<T> là ví dụ rõ ràng nhất. Dưới đây là ba ví dụ về các phương pháp có các biến thể trên một tham số. Trong mỗi trường hợp, chúng tôi sẽ cố gắng lấy một mục từ danh sách và thêm một mục khác.

// Very strict - only a genuine List<T> will do 
public void Foo(List<T> list) 
{ 
    T element = list.get(0); // Valid 
    list.add(element); // Valid 
} 

// Lax in one way: allows any List that's a List of a type 
// derived from T. 
public void Foo(List<? extends T> list) 
{ 
    T element = list.get(0); // Valid 
    // Invalid - this could be a list of a different type. 
    // We don't want to add an Object to a List<String> 
    list.add(element); 
} 

// Lax in the other way: allows any List that's a List of a type 
// upwards in T's inheritance hierarchy 
public void Foo(List<? super T> list) 
{ 
    // Invalid - we could be asking a List<Object> for a String. 
    T element = list.get(0); 
    // Valid (assuming we get the element from somewhere) 
    // the list must accept a new element of type T 
    list.add(element); 
} 

Để biết thêm chi tiết, đọc:

+0

Lớp ZipEntrySubclass như JarEntry (lý do tại sao ZipFile.entries sử dụng ký tự đại diện)? –

+0

Cảm ơn Tom - sẽ chỉnh sửa câu trả lời của tôi :) –

4

Vâng, trực tiếp từ một trong những sun generics tutorials:

Ở đây Hình dạng là lớp trừu tượng với ba lớp con: Hình tròn, Hình chữ nhật, và Hình tam giác.

public void draw(List<Shape> shape) { 
    for(Shape s: shape) { 
    s.draw(this); 
    } 
} 

Điều đáng chú ý là phương pháp bốc thăm() chỉ có thể được gọi vào danh sách Shape và không thể được gọi vào danh sách của Circle, Rectangle, và Triangle cho ví dụ. Để có phương pháp chấp nhận bất kỳ loại hình dạng, nó phải là viết như sau:

public void draw(List<? extends Shape> shape) { 
    // rest of the code is the same 
} 
+0

Đây là lần thứ hai trong tuần này Jon Skeet đã nhận được câu trả lời ngay trước tôi. Tôi đề nghị chúng tôi đề cập đến điều này như Skeeting. – GaryF

+0

có vẻ tốt. căng thẳng quá khứ sẽ là gì? Sket? "Jon Skeet trượt tôi đi!" :) – Epaga

+0

http://stackoverflow.com/questions/305223/jon-skeet-facts/317486#317486 –

0

Bây giờ bạn vừa đi và nhắc nhở tôi về một cái gì đó tôi muốn chúng tôi đã có hơn trong C# thế giới .

Khác với các liên kết được cung cấp, có một số liên kết tốt về C# và Java liên quan đến chủ đề này trong các câu trả lời cho câu hỏi này: Logic and its application to Collections.Generic and inheritance

Một lựa chọn trong số đó là:

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