2009-10-26 37 views
11

Tôi có tình huống sau đây:Java Generics để thực thi kiểu trả về của phương pháp trừu tượng

abstract class X { abstract X someMethod (...) {...} }. 

Bây giờ tôi muốn hạn chế bất kỳ thực hiện X để có phương pháp 'someMethod' của mình trở lại loại thực hiện cụ thể, chứ không chỉ X :

class X1 extends X { X1 someMethod (...) {...} }. 
class X1 extends X { X someMethod (...) {...} }. //want this to be flagged as an error 
class X2 extends X { X1 someMethod (...) {...} }. //want this to be flagged as an error too 

Có thể đạt được điều này bằng cách sử dụng Generics Java không?

EDIT

OK. Tôi chỉ hỏi có/không có câu hỏi và có một "có". Lỗi của tôi. Những gì tôi đã thực sự quan tâm là "làm thế nào để tôi viết các tờ khai".

Trả lời

17

Điều này cũng hoạt động;

abstract class X<T> { 
    public abstract T yourMethod(); 
} 
class X1 extends X<X1> { 
    public X1 yourMethod() { 
     return this; 
    } 
} 
class X2 extends X<X2> { 
    public X2 yourMethod() { 
     return this; 
    } 
} 
+5

Tôi coi đây là mã rất xấu, nhưng đó cũng là giải pháp duy nhất tôi biết, và tôi phạm tội khi sử dụng nó ... +1 – rmeador

+0

Suy nghĩ thứ hai ... có ai biết chắc chắn rằng đây là một tính năng của Jav –

+0

... của Generics Java, và không chỉ là một sản phẩm phụ nguy hiểm của cách chúng được hình thành/thực hiện? –

1

Có. Đây là return type covariance.

+2

Ông không được hỏi liệu một kiểu trả về hiệp biến được cho phép. Anh ta đang hỏi làm thế nào để thực thi nó ... – meriton

0

này nên chỉ làm việc tốt:

class X<T> { 
    abstract T someMethod(...); 
} 

class X1<T1> extends X 
    T1 someMethod(...) { 
    ... 
    } 
} 
4
abstract class X<I extends X<I>> { 
    protected X(Class<I> implClazz) { 
     if (!getClass().equals(implClazz)) { 
      throw new IllegalArgumentException(); 
     } 
    } 

    abstract I someMethod(); 
} 

Lý do: Bạn không có thể tham khảo các loại động trong loại giới hạn, do đó việc kiểm tra gián tiếp trong các nhà xây dựng.

+0

Rất cám ơn, rất hữu ích. Có thể bỏ phiếu này, nhưng tôi nhận được phản hồi "Vui lòng đăng nhập hoặc đăng ký". –

+0

Lý do lý giải tại sao giải pháp của Bjorn vẫn cho phép tôi viết "lớp X2 mở rộng X {X1 someMethod() {...}}" –

+0

Chính xác. Mục đích duy nhất của nhà xây dựng là bảo vệ chống lại điều đó. – meriton

2

Dưới đây là một cách tiếp cận cho phép bạn quay trở lại một kiểu tham số cho this:

AbstractFoo<T extends AbstractFoo<T>> { 
    /** Subclasses must implement to return {@code this}. */ 
    protected abstract T getThis(); 

    /** Does something interesting and returns this Foo */ 
    public T inheritedThing { 
    /* blah di blah */ 
    return getThis(); 
    } 
} 
Các vấn đề liên quan