2013-08-23 45 views
8

Tôi có một giao diện để đảm bảo đối tượng có thể làm bản sao của bản thân:lớp con kế thừa giao diện chung

public interface Duplicable<T extends Duplicable<T>> { 
    public T duplicate(); 
} 

tôi bây giờ có

class X implements Duplicable<X> 

nhưng tôi cũng có một Y lớp mà kéo dài X.

Đây không phải là vấn đề, cho đến khi tôi cần một lớp chung khác:

public class DoStuffWithDuplicable<T extends Duplicable<T>> 

tôi không thể sử dụng một phiên bản generic của DoStuffWithDuplicable sử dụng Y, vì nó không thực hiện Duplicable<Y> nhưng Duplicable<X> vì nó thừa hưởng nó từ X.

Vì vậy, tôi đã cố gắng

public class DoStuffWithDuplicable<T extends Duplicable<? super T>> 

.. nhưng phương tiện này sau đó giới thiệu một dàn diễn viên không an toàn

(T) obj.duplicate() 

trong phần mã. Các tham số lớp cũng phức tạp hơn và việc sử dụng lớp khó hiểu hơn. Bất kỳ ý tưởng làm thế nào để có được xung quanh vấn đề này?

+0

Bạn có thể nói lại điều này: "Tôi không thể sử dụng một phiên bản generic của DoStuffWithDuplicable sử dụng Y, vì nó hiện không triển khai Duplicable nhưng Duplicable vì nó kế thừa từ X. " ? – tbsalling

+0

xin lỗi, định dạng vấn đề – phil

+1

Như một lưu ý, đây chính xác là lý do tại sao một số nhà khoa học máy tính nói rằng tất cả các lớp phải là 'abstract' hoặc' final'. Bạn cũng sẽ gặp phải các vấn đề với 'equals'; bạn có thể refactor để loại bỏ có một instantiable 'X'? – chrylis

Trả lời

1

Tôi có thể chưa hiểu câu hỏi của bạn một cách chính xác, nhưng tôi sẽ cho phép nó đi.

Trước hết, tại sao bạn có giao diện mở rộng như vậy?

gì bạn có thể thử là:

public interface Duplicable<T> { 
    public T duplicate(); 
} 

Sau đó, khi bạn sử dụng một lớp học nơi bạn muốn tham số tổng quát để được duplicable, bạn làm điều đó như thế này:

public class X<T extends Duplicable<T>> { 
    code... 
} 

Bây giờ khi bạn kế thừa từ X, bất kỳ thành phần chung nào trong các lớp con sẽ phải trùng lặp.

+1

Tôi nghĩ rằng "tại sao" khá rõ ràng: OP muốn hạn chế 'T' cùng loại với lớp thực hiện nó. Cách của bạn cho phép, ví dụ, 'Integer' để thực hiện' Duplicable '. –

+0

@MarkoTopolnik: 1) Nhưng ràng buộc của OP không hạn chế nó. Nó không thể hạn chế nó. 2) Và ràng buộc của OP không phục vụ bất kỳ mục đích an toàn loại nào. Giao diện là loại an toàn như nó được. – newacct

+0

Các ràng buộc '>' constrains 'T' giống như cách' Enum' ràng buộc tham số kiểu của nó: 'Enum >'. 'E' phải là lớp enum. –

1

Không thể thực hiện điều này trong Java.

Giả sử bạn gọi obj.duplicate() trên một đối tượng kiểu Y. Sau đó, hệ thống kiểu chỉ có thể đảm bảo rằng nó sẽ trả về một đối tượng kiểu X, vì Y triển khai Duplicate <X>.

Nhưng bạn chỉ có thể tạo một DoStuffWithDuplicable <X> và chuyển các đối tượng Y vào nó.

DoStuffWithDuplicable<X> blub = new DoStuffWithDuplicable<X>(); 
    Y y = (Y) blub.doStuff(new Y()); 

Đối với các giá trị trả lại, ứng dụng khách của thư viện của bạn chỉ có thể sử dụng các loại an toàn.

Một tùy chọn khác sẽ được sử dụng dàn diễn viên không an toàn trong thư viện và kiểm tra các loại bằng tay:

class DoStuffWithDuplicable<T extends Duplicable<? super T>> { 
    T doStuff(T obj) { 
     @SuppressWarnings("unchecked") 
     T t = (T) obj.duplicate(); 
     if (!t.getClass().equals(obj.getClass())) 
      throw new ClassCastException("..."); 
     return t; 
    } 
} 
Các vấn đề liên quan