2013-08-22 45 views
8

Tôi đang gặp vấn đề được mô tả trong this question nhưng muốn tìm giải pháp (nếu có thể) mà không có tất cả các ký tự và chú thích @SuppressWarning.Phương pháp kế thừa được trả về kiểu tham chiếu

Một giải pháp tốt hơn sẽ là một trong đó xây dựng dựa trên tham chiếu từng người:

  • loại bỏ @SuppressWarning
  • loại bỏ phôi

Giải pháp trình bày ở đây sẽ được chấm điểm với 2 điểm dựa trên tiêu chí. Bounty đi đến giải pháp với hầu hết các điểm hoặc "thanh lịch nhất" nếu có nhiều hơn một điểm với 2 điểm.

+0

Sẽ thêm tiền thưởng trong 2 ngày do cơ chế SO cho cung cấp tiền thưởng. Bây giờ, hãy thoải mái đăng câu trả lời của bạn. – pnt

+0

liên quan: [Có cách nào để chỉ loại hiện tại có biến kiểu không?] (Http://stackoverflow.com/questions/7354740/is-there-a-way-to-refer-to-the-current -type-với-a-type-biến) –

Trả lời

9

Không dàn diễn viên, không có @SuppressWarning, vài dòng chỉ:

public abstract class SuperClass<T extends SuperClass<T>> { 
    protected T that; 
    public T chain() { 
     return that; 
    } 
} 

public class SubClass1 extends SuperClass<SubClass1> { 
    public SubClass1() { 
     that = this; 
    } 
} 

public class SubClass2 extends SuperClass<SubClass2> { 
    public SubClass2() { 
     that = this; 
    } 
} 
+1

Điều này đã được chọn là câu trả lời hay nhất vì nó tránh hoàn toàn phôi, không có @SuppresWarnings và, theo tôi, thanh lịch nhất vì nó cũng tránh ghi đè phương pháp (tham chiếu mà bạn phải "ghi đè" trông sạch hơn và yêu cầu ít mã hơn, nó cũng bị ẩn khỏi người dùng mà bạn ghi đè bất kỳ thứ gì). Sẽ thưởng tiền thưởng trong 23 giờ. – pnt

+0

@pnt Đây là giải pháp cơ bản giống như câu trả lời được chấp nhận trong câu hỏi được tham chiếu của bạn. Tại sao bạn không thích nó ở đó và chấp nhận nó ở đây? –

+1

@FrancoisBourgeois Thực ra, đây không phải là giải pháp tương tự. Trong giải pháp khác, với 'return (T) this;' trong lớp trừu tượng, trình biên dịch không thể biết tại thời gian biên dịch nếu cast là an toàn (ngay cả khi nó có thể được, chỉ có nhà phát triển biết), do đó cần chú thích @SuppressWarning. Trong giải pháp của tôi, không cần phải cast vì 'that' được đặt trực tiếp trong lớp con. Và giải pháp * không đúc này * là điều được đặt ra ở đây. – sp00m

1

Một giải pháp là ghi đè phương thức trong lớp con và thay đổi kiểu trả về thành phương thức cụ thể hơn, ví dụ: loại trẻ em. Điều này đòi hỏi phải đúc. Thay vì sử dụng điển hình (Child) dàn diễn viên, sử dụng phương pháp Class#cast(Object)

public class Parent { 
    public Parent example() { 
     System.out.println(this.getClass().getCanonicalName()); 
     return this; 
    } 
} 

public class Child extends Parent { 
    public Child example() { 
     return Child.class.cast(super.example()); 
    } 

    public Child method() { 
     return this; 
    } 
} 

Dàn diễn viên được ẩn trong các phương pháp tiêu chuẩn. Từ nguồn của Class.

public T cast(Object obj) { 
    if (obj != null && !isInstance(obj)) 
     throw new ClassCastException(cannotCastMsg(obj)); 
    return (T) obj; 
} 
+0

Không thực sự là một giải pháp bởi vì nó không loại bỏ các phôi (chỉ cần kết thúc tốt đẹp và giấu chúng) và không giải quyết được vấn đề ban đầu trong câu hỏi được tham chiếu. Có, tất nhiên bạn có thể ghi đè lên phương thức để trả về một loại cụ thể hơn nhưng toàn bộ vấn đề là sử dụng lại nó và không phải ghi đè lên nó trong mỗi đứa trẻ. – pnt

+0

@pnt Vấn đề được nêu là _I muốn thực hiện điều này mà không cần sử dụng các giao diện bổ sung và các phương thức bổ sung, và để sử dụng nó mà không có lớp phôi, đối số phụ và vân vân._ Điều bạn không thể. Các giải pháp được đề xuất đều có phương pháp bổ sung và/hoặc các đối số bổ sung. Hoặc là bạn ghi đè lên phương thức được đề cập hoặc bạn giới thiệu một phương thức khác trong phụ huynh và ghi đè lên phương thức đó. Trong giải pháp Generics, bạn cũng cần giới thiệu một tham số kiểu. –

5

Một cách tiếp cận là để xác định một phương pháp trừu tượng getThis() trong Parent lớp, và làm cho tất cả các Child lớp ghi đè lên nó, trả lại this tham khảo. Đây là một cách để khôi phục kiểu đối tượng this trong một hệ thống phân cấp lớp.

Mã này sẽ trông như thế này:

abstract class Parent<T extends Parent<T>> { 

    protected abstract T getThis(); 

    public T example() { 
     System.out.println(this.getClass().getCanonicalName()); 
     return getThis();   
    } 
} 

class ChildA extends Parent<ChildA> { 

    @Override 
    protected ChildA getThis() { 
     return this; 
    } 

    public ChildA childAMethod() { 
     System.out.println(this.getClass().getCanonicalName()); 
     return this; 
    } 
} 

class ChildB extends Parent<ChildB> { 

    @Override 
    protected ChildB getThis() { 
     return this; 
    } 

    public ChildB childBMethod() { 
     return this; 
    } 
} 


public class Main { 

    public static void main(String[] args) throws NoSuchMethodException { 
     ChildA childA = new ChildA(); 
     ChildB childB = new ChildB(); 

     childA.example().childAMethod().example(); 
     childB.example().childBMethod().example(); 
    } 
} 

Theo yêu cầu, không có Đúc và không @SuppressWarnings. Tôi đã học được mẹo này vài ngày từ Angelika Langer - Java Generics FAQs.

tham khảo:

+1

Bạn có thể muốn khai báo 'Parent >'. Nếu không, bạn có thể làm 'mở rộng Parent ' và phương thức chuỗi sẽ kết thúc tại 'String getThis()'. –

+0

@SotiriosDelimanolis. Ah! Đúng. Cảm ơn :) –

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