2010-01-30 48 views
6

Tôi đang cố gắng gửi các đối tượng đến phương thức riêng biệt theo phân lớp của chúng.Làm thế nào để gọi một phương thức java dựa trên một loại phân lớp?

Ví dụ, hãy xem xét những 2 đối tượng

class A extends I {} 
class B extends I {} 

và phương pháp

void dispatch(I i) {} 

trong dispatch(), tôi muốn gọi một phương thức theo kiểu i. Do đó nếu i thực sự thuộc loại A, phương thức handlerA(A a) sẽ được gọi. Nếu đó là loại B, handlerB(B b) sẽ được gọi, v.v ... Tôi đã thử với quá tải phương thức nhưng tôi đoán nó không hoạt động theo cách này

cách tốt nhất để đạt được điều này là gì? Tôi muốn tránh sử dụng if/else statement ...

Xin cảm ơn trước,

chỉnh sửa: Tôi không thể sửa đổi bất kỳ lớp nào trong số đó.

Trả lời

3

Vì vậy, trong I bạn khai báo phương pháp handler() và triển khai phương thức thích hợp (tức là khác) trong cả hai AB.

Đây là đa hình :)

+0

này giả định rằng 'handler()' làm cho tinh thần để có trên 'A' và 'b'. Nếu đúng như vậy, câu trả lời của bạn chính xác 100%. –

+0

Kevin: Đúng vậy. Nhưng chỉ là loại. Tôi vẫn nghĩ rằng OP là thiếu khái niệm cơ bản của đa hình, và ngay cả khi đề nghị chính xác của tôi là không phù hợp, tôi nghĩ rằng một số đề án của một chức năng/tài sản trong 'tôi' là con đường để đi. –

+0

nếu xử lý() là trong I, và cả A và B thực hiện tôi, nhưng nó không có ý nghĩa để có handler() trên cả hai, tôi nghĩ rằng có ** có lẽ ** vấn đề khác. – Carl

2

Sử dụng Visitor Pattern.

Tóm lại, có I khai báo phương thức accept(Visitor<T> ...) và có Visitor hiển thị onA(A ...), onB(B ...), v.v. Việc triển khai giao diện I của bạn sẽ gọi phương thức thích hợp trên phương thức được chuyển vào số Visitor<T>.

Nó có thể không đáng giá (do boilerplate) nếu bạn chỉ có 2 lớp cụ thể, nhưng ở đâu đó khoảng 3 hoặc 4 nó bắt đầu đáng giá - nếu chỉ để tránh trùng lặp nếu các cấu trúc khác.

1

Vì chỉnh sửa của bạn, tôi cho rằng bạn không thể chỉnh sửa A, B và I; điều này dẫn đến tin xấu:

Bạn có thể kế thừa từ A nói C trong lớp này (C), bạn có thể gọi super.dispatch() để bạn có thể đạt được lớp cơ sở A.dispatch().

  • Nhưng do thiết kế (thừa kế không được giám sát), bạn không thể truy cập I. Điều này sẽ giống như gọi super.super không được phép

  • Trong Java, bạn không thể gọi super(). Super() .. Trẻ em có liên quan đến cha mẹ của chúng, nhưng không cho cha mẹ của chúng.

Vì vậy, bạn là nạn nhân của thiết kế kém. EDIT: sửa lỗi typo

0

Có vẻ như cách duy nhất bạn có thể thực hiện việc này là sử dụng tính năng kiểm tra kiểu. Tôi hiểu rằng điều này không được khuyến khích, nhưng ...

void dispatch(I i) 
{ 
    if(i instanceof A) 
    { 
     handlerA(); 
    } 
    else 
    { 
     handlerB(); 
    } 
} 

Nhưng nghiêm túc, nếu bạn có thể tránh nó, đừng viết mã như thế này. Nếu bạn không thể sửa đổi chúng, bạn có thể mở rộng A và B bằng cách sử dụng một phương thức handler() khác cho cả hai và và sử dụng các lớp con mới thay vì A và B?

0

Tôi nghĩ rằng Adapter Pattern có thể áp dụng nhiều hơn Mẫu khách truy cập trong trường hợp này.

+0

chính xác như thế nào? (15) – Bozho

0

Nếu bạn có thể sử dụng Scala, bạn có thể viết

i match { 
    case a: A => handlerA(a) 
    case b: B => handlerB(b) 
    case _ => throw new Exception("Unknown i: " + i.toString) 
} 
Các vấn đề liên quan