2012-06-08 42 views
27

Tôi đang gặp vấn đề khi hiểu phần này của "Kiểm tra bình đẳng lớp" được định nghĩa trong hướng dẫn táo."Thử nghiệm đẳng cấp bình đẳng" trong mục tiêu-c

Trong lớp con được tạo động, phương thức lớp thường được ghi đè sao cho lớp con giả mạo làm lớp thay thế. Khi thử nghiệm cho đẳng thức đẳng cấp, bạn nên so sánh các giá trị được trả về bởi phương thức lớp chứ không phải các giá trị được trả về bởi các hàm mức thấp hơn. Đặt về API, sự bất bình đẳng sau đây liên quan cho lớp con năng động:

[object class] != object_getClass(object) != *((Class*)object) 

Bạn do đó nên kiểm tra hai lớp cho bình đẳng như sau:

if ([objectA class] == [objectB class]) { //... 
+6

hoặc isMemberOfClass - http://stackoverflow.com/questions/383978/how-useful-is-the-nsobject-ismemberofclass-method – 9dan

+1

Mục tiêu của bạn ở đây là gì? Bạn đang thử nghiệm lớp của một đối tượng, hoặc so sánh các lớp của hai đối tượng, hoặc ...? Chắc chắn '* ((Class *) đối tượng)' sẽ không bằng kết quả của một trong hai thủ tục để có được đối tượng lớp - bạn không thể chỉ đúc một thể hiện cho một lớp (cũng là, loại 'Lớp' đã một con trỏ). –

+0

xin lỗi tôi quên đề cập đến từ hướng dẫn táo của nó, và tôi không nhận được điều này toàn bộ đẳng cấp thử nghiệm ... toàn bộ para này là từ hướng dẫn táo ... –

Trả lời

40

Có những tình huống trong đó mọi người thêm các lớp mới vào thời gian chạy. Một ví dụ là quan sát giá trị khóa: khi bạn quan sát một đối tượng, khung công tác Foundation tạo ra một lớp con mới của lớp của đối tượng quan sát được. Lớp năng động này hoạt động giống như lớp cha của nó, nhưng thêm thông báo KVO vào tất cả các phương thức của trình biến đổi.

Đoạn bạn trích dẫn cho biết thời gian chạy Objective-C có thể cho biết lớp mới này ngoài lớp gốc. Tuy nhiên, bởi vì nó chỉ là một chi tiết thực hiện của cách KVO được xây dựng, bạn không nên biết hoặc quan tâm đến nó. Do đó, các nhà phát triển đã vượt qua phương pháp -class của lớp mới của họ, giả vờ rằng các đối tượng vẫn là thành viên của lớp gốc.

Nếu bạn muốn kiểm tra xem hai đối tượng có thuộc cùng một lớp hay không, bạn phải so sánh kết quả của các phương thức -class (có các thủ thuật như KVO), thay vì sử dụng các hàm thời gian chạy.

Dưới đây là một ví dụ:

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

int main(int argc, const char * argv[]) 
{ 
    @autoreleasepool { 
     NSObject *observer = [NSObject new]; 
     NSObject *model = [NSObject new]; 

     [model addObserver: observer forKeyPath: @"count" options: 0 context: NULL]; 

     //using -class methods: 
     NSLog(@"model is a %@, observer is a %@", [model class], [observer class]); 

     //casting to Class: 
     NSLog(@"model is a %@, observer is a %@", *(Class*)model, *(Class*)observer); 

     //using the runtime: 
     NSLog(@"model is a %@, observer is a %@", object_getClass(model), object_getClass(observer)); 

     [model removeObserver: observer forKeyPath: @"count" context: NULL]; 
     [model release]; 
     [observer release]; 
    } 
    return 0; 
} 

Bạn thấy rằng tất cả những gì đang làm là tạo ra hai đối tượng, nói với một trong số họ để quan sát khác, sau đó tìm ra những gì các lớp học của họ. Dưới đây là kết quả:

2012-06-08 08: 37: 26,904 Untitled 2 [896: 707] mô hình là một NSObject, quan sát là một NSObject

2012-06-08 08:37 : 26,907 Untitled 2 [896: 707] mô hình là một NSKVONotifying_NSObject, quan sát viên là một NSObject

2012-06-08 08: 37: 26,907 Untitled 2 [896: 707] mô hình là một NSKVONotifying_NSObject, quan sát viên là một NSObject

Vì vậy, như các tài liệu cho thấy, nó chỉ là trường hợp đầu tiên (nơi chúng tôi so sánh -class) mà làm bất cứ điều gì mã ứng dụng có thể mong đợi hợp lý. Hai cách khác để tìm ra lớp - hỏi thời gian chạy, và đưa con trỏ đối tượng đến một số Class * - cả hai cung cấp các chi tiết thực hiện về cách KVO đã thay đổi lớp từ bên dưới chúng ta, và có nghĩa là so sánh lớp bây giờ sẽ không hiển thị rằng các lớp đều bình đẳng.

Bởi vì câu trả lời và ý kiến ​​khác được đề cập đến -isMemberOfClass:-isKindOfClass:, tôi sẽ giới thiệu những điểm quá:

  • -isKindOfClass:không một thử nghiệm cho bình đẳng giai cấp. [object isKindOfClass: aClass] là đúng nếu object là một phiên bản của aClasshoặc bất kỳ lớp con nào của nó. Vì đoạn văn bạn đã trích dẫn là về sự bình đẳng của lớp, -isKindOfClass: không có liên quan ở đây. Điều đó nói rằng, nó thường xuyên nhất là thử nghiệm mà bạn muốn làm trong mã ứng dụng. Thông thường, bạn cần quan tâm đến câu trả lời cho "Tôi có thể sử dụng đối tượng này làm Foo không?" "đối tượng này có phải là một đối tượng chính xác của Foo không?".

  • -isMemberOfClass: là phép thử cho đẳng thức bình đẳng: [object isMemberOfClass: aClass] chỉ đúng nếu đối tượng là một phiên bản aClass. Thử nghiệm này được thực hiện bằng cách sử dụng kết quả của phương pháp -class, có nghĩa là trong ví dụ này modelsẽ kiểm tra dương tính cho [model isMemberOfClass: [NSObject class]].

+0

Mô hình '* (Class *)' có được ưu tiên hơn' * (model-> isa) 'không? –

+1

Không được ưu tiên, vì cả hai đều dựa vào việc phá vỡ đóng gói theo cách mà '-class' không. –

5

Nó nên là:

if([objctA isKindOfClass [MyClass class]]) 
+6

Đó là một thử nghiệm khác. 'isKindOfClass:' không kiểm tra sự bình đẳng của lớp, nó kiểm tra đối tượng được thử nghiệm là một thành viên của lớp được chỉ định _hoặc bất kỳ lớp con nào. –

1

Có thể bạn sử dụng phương thức 'NSStringFromClass' và so sánh các chuỗi thu được nhờ 'isEqualToString'?

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