2010-06-29 44 views
6

Trong mã một của tôi đã như sau cha trừu tượngSử dụng loại chung của một phân lớp trong lớp siêu trừu tượng của nó?

public abstract class AbstractClass<Type extends A> {...} 

và một số lớp trẻ như

public class ChildClassA extends AbstractClass<GenericTypeA> {...} 

public class ChildClassB extends AbstractClass<GenericTypeB> {...} 

tôi đang tìm kiếm một cách thanh lịch làm thế nào tôi có thể sử dụng các loại chung của các lớp con (GenericTypeA, GenericTypeB, ...) bên trong lớp trừu tượng theo cách tổng quát.

Để giải quyết vấn đề này, tôi đang định nghĩa phương pháp

protected abstract Class<Type> getGenericTypeClass(); 

trong lớp trừu tượng của tôi và thực hiện phương pháp này

@Override 
protected Class<GenericType> getGenericTypeClass() { 
    return GenericType.class; 
} 

trong mỗi lớp trẻ.

Có thể lấy loại chung của các lớp con trong lớp trừu tượng của tôi mà không cần triển khai phương thức trợ giúp này không?

BR,

Markus

Trả lời

10

Tôi nghĩ có thể. Tôi thấy điều này đã được sử dụng trong các mẫu DAO cùng với Generics. ví dụ. Hãy xem xét các lớp:

public class A {} 
public class B extends A {} 

Và lớp generic của bạn:

import java.lang.reflect.ParameterizedType; 
    public abstract class Test<T extends A> { 

    private Class<T> theType; 

    public Test() { 
     theType = (Class<T>) (
       (ParameterizedType) getClass().getGenericSuperclass()) 
       .getActualTypeArguments()[0]; 
    } 

    // this method will always return the type that extends class "A" 
    public Class<T> getTheType() { 
     return theType; 
    } 

    public void printType() { 
     Class<T> clazz = getTheType(); 
     System.out.println(clazz); 
    } 
    } 

Bạn có thể có một lớp Test1 kéo dài thử nghiệm với lớp B (nó kéo dài Một)

public class Test1 extends Test<B> { 

    public static void main(String[] args) { 
     Test1 t = new Test1(); 

     Class<B> clazz = t.getTheType(); 

     System.out.println(clazz); // will print 'class B' 
     System.out.println(printType()); // will print 'class B' 
    } 
    } 
+0

Tôi không hiểu mã nguồn trong hàm tạo của Test thực sự làm gì, nhưng nó hoạt động. Bây giờ tôi không phải sử dụng các phương thức trợ giúp nữa. Thanks :-) – Markus

+2

Nó sử dụng sự phản chiếu.Đầu tiên nó nhận được lớp chung (java.lang.reflect.Type) của lớp, trong trường hợp của chúng ta nó sẽ không bao giờ rỗng và chúng ta biết rằng nó là một ParameterizedType, vì vậy chúng ta bỏ nó và gọi phương thức getActualTypeArguents trả về một mảng các đối số kiểu thực tế ví dụ B, thuộc loại. – naikus

+0

Ahhh, cảm ơn lời giải thích của bạn. – Markus

0

Tôi không chắc tôi hoàn toàn hiểu câu hỏi của bạn - <Type> kiểu generic của lớp con, ngay cả khi nó được trình bày trong lớp trừu tượng. Ví dụ, nếu cha trừu tượng của bạn định nghĩa một phương pháp:

public void augment(Type entity) { 
    ... 
} 

và bạn nhanh chóng một ChildClassA, bạn sẽ chỉ có thể gọi augment với một thể hiện của GenericTypeA.

Bây giờ nếu bạn muốn một lớp học theo nghĩa đen, thì bạn sẽ cần phải cung cấp phương thức như bạn đã chỉ ra. Nhưng nếu bạn chỉ muốn tham số chung, bạn không cần phải làm bất cứ điều gì đặc biệt.

+0

Xin lỗi, tôi don 't thực sự có quan điểm của bạn. Kiểu được mở rộng bởi các kiểu generic của các lớp con. Do đó có thể bỏ kiểu của lớp con trở lại Type và sử dụng nó bên trong lớp siêu trừu tượng. – Markus

+0

@Markus - Bây giờ * Tôi * không hiểu câu thứ hai của bạn, tôi không nghĩ rằng nó có ý nghĩa. Bạn không thể truyền tham số kiểu theo bất kỳ nghĩa nào; trong định nghĩa lớp, nó chỉ đơn thuần là một trình giữ chỗ trỏ đến kiểu mà bạn thực sự tạo ra một đối tượng. Và các lớp con không * mở rộng * loại, chúng cung cấp một ràng buộc cụ thể cho nó. Vì vậy, khi các phương thức trong 'AbstractClass' đang được gọi cho một thể hiện của' ChildClassA', 'type' ** là **' GenericTypeA'. –

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