2012-01-03 38 views
7

tôi muốn làm một cái gì đó giống nhưGeneric với Loại Arguments Biến

public interface Foo<R, P...> { 
    public R bar(P...) {/*misc*/} 
} 

để có được một mảng của các loại sử dụng trong việc thực hiện ràng buộc tôi. Điều này có thể trong java?

Varargs được thiết kế để cho phép tôi có bất kỳ số đối số nào của một lớp nhất định.

Tôi muốn sử dụng nó (hoặc một cái gì đó tương tự) để phương pháp của tôi chấp nhận một số đối số, mỗi đối tượng trong số đó là thành viên của một lớp khác. Các lớp này được định nghĩa khi generic bị ràng buộc.

Tôi biết có xung quanh, nhưng có cách nào an toàn để thực hiện việc này không?

+0

Có gì sai với những gì bạn đã có cho đến nay? Vấn đề duy nhất là varags không chơi khủng khiếp độc đáo với generics. –

Trả lời

7

Vì bạn dường như muốn để có thể làm cho bar mất nhiều tham số của loại khác nhau (một cái gì đó varargs không sử dụng cho), tôi muốn đề nghị làm cho nó thay vì phải mất một tham số duy nhất. Sau đó, bạn có thể đặt tham số đơn lẻ đó thành một vùng chứa chứa từng "tham số" riêng lẻ mà bạn muốn sử dụng.

Nói chung, tốt nhất nên tạo một lớp cho mỗi bộ tham số bạn muốn sử dụng với phương pháp này để bạn có tên tốt cho mỗi đối tượng chứa trong đó. Tuy nhiên, bạn cũng có thể thực hiện một số việc như tạo một loạt các loại bộ dữ liệu (chẳng hạn như Pair) để sử dụng làm chủ sở hữu.

Dưới đây là một ví dụ:

public class Foo<R, P> { 
    /* 
    * Not sure how you intend to provide any kind of implementation 
    * here since you don't know what R or P are. 
    */ 
    public R bar(P parameters) { ... } 
} 

public class SomeFoo extends Foo<SomeResult, Pair<Baz, Bar>> { 
    public SomeResult bar(Pair<Baz, Bar> parameters) { ... } 
} 

SomeFoo foo = ... 
SomeResult result = foo.bar(Pair.of(baz, bar)); 
+0

Tôi nghĩ rằng đây là một ý tưởng hay, nó cho phép lớp ràng buộc xác định số lượng và kiểu đối số, bằng cách gói chúng trong một đối tượng container/tuple. Phần tuple/pair của các thư viện lõi/jdk? Tôi không thể tìm thấy chúng, mặc dù tôi tưởng tượng nó sẽ là tầm thường để viết của riêng tôi. Tôi có đúng không khi gợi ý rằng các tuple trong java hoàn thành chính xác vai trò của các cấu trúc trong c? –

+2

Nói chung, tôi sẽ tránh tạo các loại tuple (chúng không tồn tại trong JDK bởi vì chúng không hoạt động tốt vì nhiều lý do) và tạo các lớp thực cho mỗi đối tượng chứa một tên hữu ích. Tôi chủ yếu chỉ đề cập rằng bởi vì nó gần với những gì bạn dường như yêu cầu và bởi vì nó là một lựa chọn mà bạn có. Câu trả lời ngắn gọn là nếu bạn muốn nhóm một số lượng tùy ý các đối tượng tùy ý, một lớp là cách để đi. Bạn có thể làm cho một lớp học rất nhỏ và đơn giản và về cơ bản nó hoạt động như một cấu trúc. – ColinD

+1

Eclipse thực sự có một tính năng để tự động thực hiện điều này: 'refactor> giới thiệu đối tượng tham số ' – AJMansfield

2

Bạn đã viết:

Tôi muốn sử dụng nó (hoặc một cái gì đó tương tự) để có phương pháp của tôi chấp nhận một số lập luận, mỗi trong số đó là thành viên của một số khác nhau cho trước lớp.

Tôi không nghĩ rằng có thể thực hiện điều này một cách an toàn mà không gặp phải một số lỗi xấu, như bao gồm một thể hiện của Class cùng với đối tượng.

Vấn đề là, với VarArgs bạn đang thực sự được truyền trong một mảng. Nhưng bạn không thể có một mảng với các loại đối tượng khác nhau, tất cả chúng phải giống nhau (hoặc các lớp con, vì vậy nếu bạn có X [] y thì mỗi phần tử phải là một phân lớp của X)

Nếu chức năng của bạn thực sự có thể đối phó với nhiều loại, bạn có thể tạo ra một cái gì đó giống như một lớp học lưu trữ một thể hiện của Class cùng với một thể hiện của T, và vượt qua trong một danh sách var args của container đó.

Vì vậy, ví dụ bạn có thể có

class TypedInstance<T>{ 
    Class<T> type; 
    T instance; 
} 

và sau đó có một chức năng mà trông giống như

public whatever(TypedInstance<? extends Object>... whatever){ 
    ... 
    doSomethingWith(whatever[0].type, whatever[0].instance); 
    ... 
} 

Những loại hacks là cần thiết vì loại chô bôi Java. Tham số chung được loại bỏ trong thời gian chạy, vì vậy nếu bạn muốn sử dụng nó, bạn phải đặt nó trở lại.

+0

+1 Ý tưởng hay, nhưng hàm này không bao giờ sử dụng P. Không có loại an toàn cho các kiểu tham số khác ngoài việc chúng phải mở rộng Object. Loại 'instance' có thể được mua bởi instance.getClass(); về cơ bản bạn đang gói một thể hiện của loại T trong một wrapper , đó là một chút vô nghĩa. –

+0

Đúng, nhưng không có cách nào thực sự để làm điều này một cách trực tiếp ... mặc dù ý tưởng của Colin D về việc sử dụng các tập tin lồng nhau là khá rực rỡ. Nhắc tôi về cách mọi thứ được thực hiện trong Đề án/lisp. –

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