2009-05-29 28 views
21

Tôi có một baseclass, Statement, mà một số lớp khác kế thừa từ, có tên IfStatement, WhereStatement, v.v ... Cách tốt nhất để thực hiện thử nghiệm trong một if là gì tuyên bố để xác định loại Statement lớp một trường hợp có nguồn gốc từ?Java có phương pháp thử nghiệm "kiểu lớp" không

Trả lời

53
if (obj.getClass().isInstance(Statement.class)) { 
    doStuffWithStatements((Statement) obj)); 
} 

Điều tốt đẹp về kỹ thuật này (trái với từ khóa "instanceof") là bạn có thể vượt qua lớp thử nghiệm xung quanh làm đối tượng. Nhưng, yeah, khác hơn thế, nó giống hệt với "instanceof".

LƯU Ý: Tôi đã cố tình tránh biên tập về việc có kiểm tra loại cá thể hay không là phải điều cần làm. Yeah, trong hầu hết các trường hợp, tốt hơn là sử dụng đa hình. Nhưng đó không phải là những gì OP hỏi, và tôi chỉ trả lời câu hỏi của anh ấy.

+3

Tại sao không chỉ sử dụng kiểm tra instanceof đơn giản hơn? –

+5

instanceof không phải là ác như goto. Có một lý do khiến nó được thêm vào ngôn ngữ và tại sao nó không bị phản đối. –

+10

+1 không phải là "chỉnh sửa về việc có kiểm tra loại cá thể hay không là điều đúng để làm" –

64
if(object instanceof WhereStatement) { 
    WhereStatement where = (WhereStatement) object; 
    doSomething(where); 
} 

Lưu ý rằng mã này thường có nghĩa là lớp cơ sở của bạn thiếu phương pháp đa hình. tức là doSomething() phải là phương thức Statement, có thể là trừu tượng, được ghi đè bởi các lớp con.

+0

Cảm ơn bạn đã cung cấp thông tin bổ sung! Tôi sẽ xem xét nó để xem nếu có một cách sạch sẽ để cải thiện thiết kế. –

+5

+1 cho câu trả lời, mặc dù tôi sẽ thêm rằng 'instanceof' có rất nhiều sử dụng hợp lệ - nó không phải luôn luôn là một mùi thiết kế. Ví dụ, nếu 'doSomething()' chỉ có thể áp dụng cho các mệnh đề thì mẫu này có lẽ tốt hơn là tạo một phần 'doSomething()' của lớp Statement (nơi nó không hợp lý). – mikera

+0

Một ví dụ khác về nơi 'instanceof' hữu ích. Trong JavaFX, bạn có một Pane. Tôi cần phải đi qua cây của các nút con. 'getChildren()' trả về các nút. Nhưng nếu một trong các nút là một Pane, tôi cũng cần phải đi qua các em _its_. Node không có phương thức 'getChildren()' và không phải là của tôi để thêm vào. Vì vậy, tôi phải sử dụng 'nút instanceof Pane' để xem liệu tôi có cần truyền Node tới một Pane và đi qua các con của nó hay không. – dwilliss

6

Câu trả lời cho câu hỏi của bạn là instanceof.

Tuy nhiên, hãy nhớ rằng nếu mã của bạn cần instanceof, đó là dấu hiệu cho thấy có điều gì đó không phù hợp với thiết kế của bạn. Có một số trường hợp khi instanceof là hợp lý, nhưng chúng khá ngoại lệ. Thông thường, nếu các lớp con của bạn cần phải hoạt động khác nhau, bạn phải sử dụng đa hình thay vì if() s.

+0

Điều duy nhất tôi sẽ thêm vào lời khen của bạn là gợi ý mạnh mẽ về lập trình bằng giao diện. – monksy

0

Đây là không phải là cách để thực hiện mọi thứ theo cách hướng đối tượng, đó là một sự trở lại đối với sự phân đôi mã/dữ liệu cũ. Bây giờ, đó không nhất thiết là một điều xấu (nếu bạn biết bạn đang làm gì) nhưng bạn nên để các ngôn ngữ không hướng đối tượng như C.

Với thiết kế phù hợp, bạn không cần loại hành vi đó . Thay vì xây dựng:

if (obj.getClass().isInstance(Statement.class)) { 
    doStuffWithStatements((Statement) obj)); 
} 

(lời xin lỗi đến benjismith cho 'ăn cắp' mã số của mình), bạn thực sự nên được làm cho đối tượng tự chịu trách nhiệm về hoạt động của mình như sau:

obj.doStuff(); 

Sau đó, mỗi khác nhau obj lớp học sẽ có định nghĩa riêng cho doStuff. Đó là cách đúng đắn để làm điều đó.

+0

Nếu chỉ có một lớp con có thể làm doStuff (™ paxdiabio) và bạn có một mảng các đối tượng trong đó một lớp siêu lớp của lớp con thì đây là cách tốt hơn để làm điều đó (thay vì thêm no-op'd các phương thức doStuff cho các siêu lớp có thể vô nghĩa (hoặc "chỉ sai")). – geowar

+0

@geowar, nếu bạn có một bộ sưu tập những thứ không đồng nhất, chúng có thể không * được * trong bộ sưu tập. Hoặc, ở mức tối thiểu, bạn không nên lặp qua bộ sưu tập đó theo cách muốn làm doStuff. Có nhiều cách khác nhau để xử lý việc này nhưng buộc nó vào tên hoặc loại của lớp có thể rất có vấn đề khi thực hiện thay đổi. Trong thế giới thừa kế/OO, có một hàm rỗng cho lớp cha mà không muốn làm gì cho trường hợp này thực sự là một giải pháp hợp lệ, làm cho mã xử lý trở nên sạch hơn. – paxdiablo

1

Hãy thử điều này:

if (Statement.class.isInstance(obj)) { 
    doStuffWithStatements((Statement) obj)); 
} 

từ Class.isInstance() phương pháp có một trường hợp đối tượng như một tham số.

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