2011-12-14 34 views
11

Trong mục tiêu-c 2.0 tại sao các lớp con cần tham chiếu các biến mẫu trong các lớp cha bằng cách sử dụng từ khóa self?Kế thừa các biến mẫu trong Mục tiêu-c

Hãy xem xét ví dụ sau:

// a.h 
@interface MyClass : NSObject 
@property (nonatomic, retain) Object *myObject; 
@end 

// a.m 
@implementation MyClass 
@synthesize myObject; 
@end 


// b.h 
@interface AnotherClass : MyClass 
@end 

// b.m 
@implementation AnotherClass 
- (void) someMethod { 
    // error 
    // Object *obj = myObject; 

    // works 
    // Object *obj = self.myObject; 
} 
@end 
+2

Điều này được giải thích bằng [câu trả lời của Kevin Ballard] (http://stackoverflow.com/a/8511046/) tới [Khả năng hiển thị của các tổng hợp ivars là gì?] (Http://stackoverflow.com/questions/8510464/) từ một vài giờ trước. –

Trả lời

11

Bạn chưa thực sự định nghĩa một biến, bạn chỉ định một tài sản (mà ngầm định nghĩa một biến đó là tư nhân). Và vì thuộc tính chỉ là phương thức, bạn cần cú pháp dấu chấm. Lưu ý rằng self.property giống với [self property].

Để khắc phục điều này, hãy chỉ định biến. Tôi sẽ cung cấp cho bạn một ví dụ trong đó biến có tên khác với thuộc tính. Hầu hết mọi người đã chọn cùng một tên cho cả hai nhưng tôi muốn có chúng khác nhau vì vậy tôi ngay lập tức nhìn thấy cái nào là có nghĩa là.

// a.h 
@interface MyClass : NSObject { 
    // Instance variables are "protected" by default, except if you 
    // use @private or @public. 
    Object *myObjectVar; 
} 

@property (nonatomic, retain) Object *myObject; 
@end 

// a.m 
@implementation MyClass 
@synthesize myObject = myObjectVar; 
@end 


// b.h 
@interface AnotherClass : MyClass 
@end 

// b.m 
@implementation AnotherClass 
- (void) someMethod { 
    // works 
    Object *obj = myObjectVar; 

    // works 
    obj = self.myObject; 

    // the same as self.myObject 
    obj = [self myObject]; 
} 
@end 

Lưu ý sự khác biệt khi bạn gán: nếu bạn gán cho biến của bạn đối tượng không được giữ lại tự động. Nhưng nó được giữ lại nếu bạn sử dụng tài sản:

myObjectVar = someObject; // not retained, old object not released! 
self.myObject = someObject; // old object released, new object retained 
[self setMyObject:someObject]; // same as the line above 

Edit: đề cập rằng các biến Ví dụ tổng hợp là tin theo mặc định, như ghi nhận của @ Jason Coco. Và @NSGod đúng là các biến mẫu bình thường là được bảo vệ theo mặc định chứ không phải công khai, đã khắc phục điều đó.

+1

Các thuộc tính '@ synthesized' thực sự tạo ra một ngà voi tên của chúng, nhưng chúng tổng hợp một ivar' @ private'. Bạn trả lời các công trình vì bạn đã tạo ra một cách cụ thể thanh công cụ và gán bộ tổng hợp cho nó với một mức truy cập ít hạn chế hơn, không phải vì các bộ tổng hợp không tạo ra các ivars. –

+0

Tôi chưa từng nói rằng các bộ tổng hợp không tạo ra những chiếc ngà, phải không? Xem câu đầu tiên của tôi. Nhưng cảm ơn vì đã làm rõ rằng họ là riêng tư. – DarkDust

+0

Ồ, bạn nói đúng. Tôi hiểu sai nó trong sự vội vàng của tôi bỏ qua các phụ huynh, xin lỗi! –

8

Chúng không, miễn là bạn thực sự khai báo một biến mẫu trong lớp cha, thay vì dựa vào khả năng tổng hợp của biến thời gian mới (ngoài việc tổng hợp các phương thức truy cập). Xem The Objective-C Programming Language: Runtime Difference để biết thêm thông tin về tổng hợp biến mẫu.

Ví dụ, để có thể tham khảo các instance variable trực tiếp, bạn sẽ cần phải thay đổi như sau:

@interface MyClass : NSObject 
@property (nonatomic, retain) Object *myObject; 
@end 

tới:

@interface MyClass : NSObject { 
// there is an implied @protected directive here 
    Object *myObject; 
} 

@property (nonatomic, retain) Object *myObject; 

@end 

Theo mặc định, các biến dụ là @protected , nghĩa là lớp và bất kỳ lớp con nào có thể truy cập trực tiếp vào các biến cá thể. @protected ivars khác với @public ivars ở chỗ bạn không thể truy cập chúng bằng cách sử dụng ->. @private ivars chỉ có thể được truy cập bởi các lớp khai báo chúng. Xem The Objective-C Programming Language: The Scope of Instance Variables để biết thêm thông tin.

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