2010-08-30 39 views
7

Tôi tiếp tục quay lại các biến thể của vấn đề này: có thể có một giải pháp rất đơn giản, nhưng tôi không thể tìm ra được ...Trả lại đối tượng lớp con từ phương thức siêu lớp

Tôi có một loạt các lớp của biểu mẫu xQuantity, ví dụ DistanceQuantity, AreaQuantity, vv, mở rộng một lớp DimensionQuantity. Bây giờ bạn có thể cộng hoặc trừ DistanceQuantity hoặc AreaQuantity, vv, nhưng bạn không thể trộn chúng, vì vậy tôi nghĩ rằng tôi cần phải có (ngắn) cộng, trừ, vv, các phương thức trong các lớp con, nhưng tôi muốn giảm bớt bất kỳ logic nào sao chép ở mức tối thiểu. Tuy nhiên, tôi cần trả về một đối tượng của lớp con, và điều này có vẻ khó thực hiện từ phương thức superclass. Tôi tin rằng điều này có thể được thực hiện bằng cách sử dụng sự phản chiếu, nhưng AFAIK bạn vẫn cần phải làm một diễn viên ở cuối trong phương pháp lớp con, và tôi nói rằng phản ánh có thể tốn kém ... Điều tốt nhất tôi đã đưa ra cho đến nay là:

Trong DistanceQuantity (và những người khác tương tự):

public DistanceQuantity() {  
} 

public DistanceQuantity add(DistanceQuantity d1) { 
    DistanceQuantity dn = new DistanceQuantity(); 
    Object o = super.add(dn, this, d1, DistanceUnit.REF_UNIT); 
    return (DistanceQuantity) o; 
} 

Trong DimensionQuantity (trừ một số báo cáo ít có liên quan):

public Object add(DimensionQuantity dn, DimensionQuantity d1, DimensionQuantity d2, 
    AbstractUnit au) { 
    dn.unit = au; 
    dn.scalar = d1.scalar + d2.scalar; 
    dn.units = dn.scalar;  
    return dn; 
} 

bất cứ ai có thể đưa ra với mã gọn gàng hơn - đó là vẫn loại- an toàn? TIA

Trả lời

8

Bạn có thể sử dụng Generics như thế này:

public abstract class DimensionQuantity<T extends DimensionQuantity>{ 
    public abstract T add(T parameter); 
} 

và bạn mở rộng nó như thế này:

public class DistanceQuantity extends DimensionQuantity<DistanceQuantity>{ 
    public DistanceQuantity add(DistanceQuantity parameter){ 
     //Whatever 
     return null; 
    } 
} 

Và cho câu hỏi ban đầu, đó là một thực sự ý tưởng tồi (và một xấu thực hành) để có một lớp bậc trên sử dụng một trong các lớp con của nó.


Resources:

Trên cùng một chủ đề:

+0

nó tốt hơn (rõ ràng hơn khi bạn có rất nhiều generics) để đặt tên cho generics một cái gì đó gần gũi hơn với T_DimensionQuantity – Egwor

+0

Bạn quên từ khóa trừu tượng. ;) Chỉ cần sử dụng 'T' là thực hành khá chuẩn mà tôi nghĩ. – Michael

+0

@mangst cảm ơn, bây giờ nó trừu tượng. @Egwor, như @mangst cho biết, T là phổ biến. T cho Type, trong Collection là E cho Element, trong Map là K và V cho Key và Value. Thông thường đó là chữ cái đầu tiên của generics của bạn có nghĩa là. –

0

Trong Java 6, bạn có thể thử một cái gì đó như thế. Nhưng sử dụng Generics cũng là một ý tưởng tốt:

public abstract class DimensionQuantity { 

    protected int quantity; 

    public DimensionQuantity (int quantity) { 
     this.quantity = quantity; 
    } 

    public abstract DimensionQuantity add(DimensionQuantity dq); 
} 

public class DistanceQuantity extends DimensionQuantity { 

    public DistanceQuantity(Quantity quantity) { 
     super(quantity); 
    } 

    /* 
    * A sub-class as return type is authorized. 
    * If dq is not a DistanceQuantity, a ClassCastException is thrown, but you can change this. 
    */ 
    @Override 
    public DistanceQuantity add(DimensionQuantity dq) throws ClassCastException { 
     return new DistanceQuantity(this.quantity + (DistanceQuantity) dq.quantity); 
    } 
} 
+0

Nhưng bây giờ bạn có thể thêm một AreaQuantity vào DistanceQuantity của bạn. –

+0

Có, nhưng điều này sẽ dẫn đến một ClassCastException. Vì vậy, hành động này bị cấm và sẽ được phát hiện một cách nhanh chóng (nhưng trong thời gian chạy và không phải là một biên dịch). –

+0

Nó thực sự nguy hiểm, và nếu bạn cast DistanceQuantity của bạn thành một DimensionQuantity bạn thậm chí không biết phải làm gì mà không mạo hiểm một CCE. –

0

Tạo một enum cho Kích thước:

enum công Dimension {AREA, khoảng cách, ...}

Ném đi lớp con của bạn. Thay vào đó, chỉ tạo các đối tượng DimensionQuantity và buộc mỗi đối tượng phải có một thứ nguyên (không thay đổi) được đặt ở thời gian tạo.

Thực hiện bổ sung trong DimensionQuantity, trước tiên hãy kiểm tra xem Thứ nguyên của hai đại lượng được thêm có giống nhau hay không.

Thì đấy! Ít lớp học hơn, an toàn loại, không có mã trùng lặp.

+0

"đầu tiên kiểm tra rằng Kích thước của hai đại lượng được thêm vào là như nhau." - Nghe có vẻ giống như thời gian chạy với tôi! –

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