2013-06-17 28 views
6

Có cách nào để tự động phát hiện từ bên trong lớp con nếu nó ghi đè phương thức cha mẹ của nó không?Mục tiêu-C phát hiện nếu lớp ghi đè phương pháp kế thừa

Class A { 
    - methodRed; 
    - methodGreen; 
    - methodBlue; 
} 
Class B inherits A { 
    - methodRed; 
} 

Từ ví dụ trên tôi muốn biết nếu lớp B có thể tự động phát hiện rằng chỉ -methodRed; được ghi đè.

Lý do tôi tự hỏi về cách tiếp cận này so với một số khả năng khác là bởi vì tôi có hàng chục lượt xem tùy chỉnh sẽ thay đổi diện mạo đó. Nó sẽ là ít hơn rất nhiều mã nếu tôi có thể tự động phát hiện các phương pháp ghi đè so với theo dõi.

Trả lời

16

Đây là khá đơn giản để kiểm tra:

if (method_getImplementation(class_getInstanceMethod(A, @selector(methodRed))) == 
    method_getImplementation(class_getInstanceMethod(B, @selector(methodRed)))) 
{ 
    // B does not override 
} 
else 
{ 
    // B overrides 
} 

tôi phải băn khoăn như thế nào biết nếu B sẽ ghi đè một phương thức trên A là hữu ích, nhưng nếu bạn muốn biết, đây là cách bạn tìm hiểu. Nó cũng có thể đáng chú ý: Trong điều kiện nghiêm ngặt mã trên xác định xem việc thực hiện cho bộ chọn trên B là khác nhau từ việc thực hiện bộ chọn trên A. Nếu bạn có một hệ thống phân cấp như A> X> B và X overrode bộ chọn, điều này sẽ vẫn báo cáo thực hiện khác nhau giữa A và B, mặc dù B không phải là lớp quan trọng. Nếu bạn muốn biết cụ thể "làm B override chọn này (không phân biệt bất cứ điều gì khác)" bạn sẽ muốn làm:

if (method_getImplementation(class_getInstanceMethod(B, @selector(methodRed))) == 
    method_getImplementation(class_getInstanceMethod(class_getSuperclass(B), @selector(methodRed)))) 
{ 
    // B does not override 
} 
else 
{ 
    // B overrides 
} 

này, có lẽ rõ ràng, đưa ra câu hỏi "làm B có một thực hiện khác nhau cho bộ chọn so với siêu lớp của nó "đó là (có lẽ cụ thể hơn) những gì bạn yêu cầu.

+0

Cảm ơn bạn đã cập nhật, điều này là tốt! Tôi sẽ cho bạn một phiếu bầu khác nhưng tôi đã tặng bạn một lá phiếu. – cnotethegr8

+2

bất kỳ ai sử dụng mã này nên '#import ' – cnotethegr8

+1

Thậm chí đơn giản hơn: 'class_getMethodImplementation()' có thể thay thế hai chuỗi cuộc gọi ở trên và có thể nhanh hơn trong một số trường hợp. Xem https://developer.apple.com/documentation/cocoa/reference/objcruntimeref để biết chi tiết. –

11

Trong lớp cơ sở của bạn:

BOOL isMethodXOverridden = [self methodForSelector:@selector(methodX)] != 
          [BaseClass instanceMethodForSelector:@selector(methodX)]; 

sẽ cung cấp cho bạn YES nếu methodX sẽ bị thay thế bởi lớp con của bạn.

Các câu trả lời ở trên cũng đúng nhưng có thể trông đẹp hơn.

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