2013-08-03 29 views
12

Đây là loại khó giải thích, nhưng tôi đã nhìn khắp mọi nơi, và tôi không thể tìm thấy bất kỳ câu trả lời hay nào.Làm cách nào để tôi có thể tham khảo loại của lớp hiện tại?

Tôi cũng đã nhìn thấy câu hỏi tràn stack How can I refer to the class type a interface is implementing in Java?How do I return an instance of an object of the same type as the class passed in using Java 6?, nhưng họ không thể trả lời câu hỏi của tôi. Có một ngoại lệ khi tôi áp dụng thừa kế.

Có một ví dụ, để làm cho nó dễ dàng hơn để hiểu:

Hãy nói rằng tôi có một số giao diện được gọi SelfMaker:

public interface SelfMaker <SELF>{ 
    public SELF getSelf(); 
} 

Và A có một con chó, mà có thể sinh sản với những con chó khác. Vì vậy, con chó là một "SelfMaker", như thế này:

public class Dog implements SelfMaker<Dog> { 
    String color; 

    public String toString() { 
     return "some " + color + " dog"; 
    } 

    public Dog procreate(Dog anotherDog) { 
     Dog son = getSelf(); 
     son.color = color; 
     return son; 
    } 

    @Override 
    public Dog getSelf() { 
     return new Dog(); 
    } 
} 

Nhưng sau đó, tôi có một DomesticDog, một con chó, nhưng nó có một gia đình đáng yêu tên ông. Như thế này:

public class DomesticDog extends Dog { 
    private String name; 

    public String toString() { 
     return super.toString() + " named " + name; 
    } 
} 

Bây giờ, tôi có một số lớp xử lý cặp vợ chồng "SelfMaker", hãy gọi lớp này là "Couple". Như thế này:

public class Couple<T extends SelfMaker<T>> { 
    private T first; 
    private T second; 

    public String toString() { 
     return first.toString() + " and " + second.toString(); 
    } 
} 

THE EXCEPTION:

Ngoại lệ đến khi tôi muốn tạo ra một vài DomesticDog s. Như thế này:

public class CoupleOfDomesticDogs extends Couple<DomesticDog>{ 
    public DomesticDog procreate(){ 
     DomesticDog son = first.procreate(second); 
     return son; 
    } 
} 

này sẽ ném một ngoại lệ trên <DomesticDog> than phiền: Bound mismatch: The type DomesticDog is not a valid substitute for the bounded parameter <T extends SelfMaker<T>> of the type Couple<T>

Tôi đã cố gắng để thay đổi biến khái quát hóa từ lớp Couple này: Couple<T extends SelfMaker<?>> nhưng "con trai" sẽ không phải là một DomesticDog (và tôi muốn "con trai" trở thành một người nội trợ). Nếu tôi thêm một số diễn viên, sau đó nó sẽ biên dịch, nhưng nó sẽ ít dễ đọc hơn.

Vì vậy, ... đây là câu hỏi: Có cách nào để đạt được điều này mà không cần đúc và tổng quát?

+0

liên quan: [Có cách nào để tham khảo các loại hiện tại với một loại biến?] (Http://stackoverflow.com/ câu hỏi/7354740/là-có-một-cách-để-tham-to-hiện-loại-với-một-kiểu-biến) –

+0

Lớp của lớp hiện tại là this.getClass(). Tên lớp là this.getClass(). GetName(). Đó là tốt như nó được. Và không có cách nào để tự động chỉ định một diễn viên trong Java. –

Trả lời

7

Không có cách nào mà tôi có thể nghĩ để làm điều này mà không cần truyền. Vấn đề của bạn sẽ được giải quyết nếu bạn ghi đè lên các phương pháp sinh sản và getSelf của DomesticDog và thay đổi phần khai báo của lớp Couple như vậy:

public class DomesticDog extends Dog { 
    private String name; 

    public DomesticDog procreate(Dog anotherDog) { 
     return (DomesticDog)super.procreate(anotherDog); 
    } 

    public Dog getSelf() { 
     return new DomesticDog(); 
    } 

    public String toString() { 
     return super.toString() + " named " + name; 
    } 
} 

public class Couple<T extends SelfMaker<? super T>> { 
    protected T first; 
    protected T second; 

    public String toString() { 
     return first.toString() + " and " + second.toString(); 
    } 
} 

Nếu bạn không muốn ghi đè getSelf() trong mỗi lớp con của Dog, bạn có thể thực hiện thay đổi sau trong lớp Dog:

public Dog getSelf() { 
    Class<? extends Dog> thisClass = this.getClass(); 
    try { 
     return thisClass.newInstance(); 
    } catch (InstantiationException e) { 
    } catch (IllegalAccessException e) { 
    } 
    throw new UnsupportedOperationException(thisClass 
         + " does not supply a public no-arg constructor"); 
} 

Điều này đảm bảo rằng tất cả các giá trị được trả về bởi getSelf() là một thể hiện của this.getClass(). Nhưng bạn vẫn sẽ phải bỏ giá trị trả về của procreate() cho các lớp con. Không có cách nào để chỉ định rõ ràng kiểu trả về là this.getClass().

+0

khá thông minh. Nhưng ... không phải là cách để nói đến loại của lớp sao? mà sẽ làm cho mã của tôi cách phù hợp hơn – Bengalaa

+2

Không, bạn không thể tham khảo rõ ràng lớp thời gian chạy của "này" với generics trừ khi bạn sử dụng ký tự đại diện hoặc đúc. Xem chỉnh sửa của tôi ở trên. –

+0

Tất cả những ý tưởng này phá vỡ hệ thống kiểu và dựa vào lập trình viên để làm điều đúng mà không cần trình biên dịch có thể kiểm tra nó. – newacct

0

Bạn sẽ phải thực hiện Dog chung và trừu tượng, với thông số loại cho biết kết quả của getSelf().Mỗi loại Dog sau đó sẽ cần phải thực hiện điều này với chính mình như là tham số:

public abstract class Dog<T> implements SelfMaker<T> { 
    String color; 

    public String toString() { 
     return "some " + color + " dog"; 
    } 

    public T procreate(T anotherDog) { 
     T son = getSelf(); 
     son.color = color; 
     return son; 
    } 

} 

public class DomesticDog extends Dog<DomesticDog> { 
    private String name; 

    public String toString() { 
     return super.toString() + " named " + name; 
    } 

    @Override 
    public DomesticDog getSelf() { 
     return new DomesticDog(); 
    } 
} 
+0

Nhưng điều gì sẽ xảy ra nếu bạn muốn tạo ra các đối tượng Dog? Hoặc nếu bạn muốn mở rộng DomesticDog để tạo một danh mục con của DomesticDogs thì sao? –

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