2011-08-22 18 views
6

Tài liệu Apple trích dẫn sau này dường như cho biết điều này được phép, mặc dù tôi sẽ thừa nhận không bao giờ có lý do để làm điều đó trong một lớp con cho đến bây giờ.Tại sao trình biên dịch cảnh báo khi redeclar thuộc tính ghi đè của lớp cơ sở là chỉ đọc trong lớp con?

Tôi có một lớp cơ sở với thuộc tính ghi đè công khai và một lớp con nơi tôi redeclare thuộc tính là chỉ đọc. Phân lớp cũng có một phần mở rộng của lớp mà một lần nữa redeclares các tài sản như readwrite để đạt được phổ biến "công cộng chỉ đọc, riêng readwrite" Objective-C mô hình. Tuy nhiên, tôi nhận được cảnh báo trình biên dịch như sau:

warning: Semantic Issue: Attribute 'readonly' of property 'foo' restricts attribute 'readwrite' of property inherited from 'Base' 

Tôi đang sử dụng Xcode 4.1 build 4B110 với LLVM 2.1 (mặc dù LLVM GCC4.2 và GCC4.2 cung cấp cho các cảnh báo tương tự) trên 10.7.

Dưới đây là một ví dụ lột xuống trưng bày các cảnh báo trình biên dịch:

#import <Foundation/Foundation.h> 

@interface Base : NSObject 
@property (nonatomic, readwrite) BOOL foo; 
@end 

@implementation Base 
@dynamic foo; 
@end 

// Subclass 
@interface Sub : Base 
@property (nonatomic, readonly) BOOL foo; 
@end 

// Class extension 
@interface Sub() 
@property (nonatomic, readwrite) BOOL foo; 
@end 

@implementation Sub 
@dynamic foo; // it warns with @synthesize as well 
@end 

Dưới đây là một đoạn có liên quan từ The Objective-C Programming Language của Apple:

tài sản khai báo lại

Bạn có thể redeclare một tài sản trong một lớp con, nhưng (ngoại trừ chỉ đọc so với ghi đè) bạn phải lặp lại các thuộc tính của nó một cách toàn bộ trong t anh ấy lớp con. Điều tương tự cũng đúng đối với một thuộc tính được khai báo trong một loại hoặc giao thức — trong khi tài sản có thể được đặt lại trong một loại hoặc giao thức, các thuộc tính của thuộc tính phải được lặp lại toàn bộ.

Nếu bạn khai báo thuộc tính trong một lớp là chỉ đọc, bạn có thể redeclare nó làm ghi đè trong phần mở rộng lớp học (xem phần "Mở rộng"), trong giao thức hoặc trong phân lớp con (xem “Phân lớp với thuộc tính”) . Trong trường hợp của một lớp học redeclaration mở rộng, thực tế là tài sản đã được redeclared trước khi cho bất kỳ @synthesize tuyên bố gây ra setter được tổng hợp. Khả năng để redeclare thuộc tính chỉ đọc khi đọc/ghi cho phép hai mẫu thực hiện phổ biến: một lớp con có thể thay đổi của một lớp bất biến (NSString, NSArray và NSDictionary là tất cả các ví dụ) và thuộc tính có API công khai là chỉ đọc nhưng thực thi ghi đè riêng tư nội bộ cho lớp học. Ví dụ sau đây cho thấy sử dụng một phần mở rộng lớp học để cung cấp một thuộc tính được khai báo là chỉ đọc trong tiêu đề công khai nhưng được redeclared riêng tư như đọc/ghi.

Tôi redeclare thuộc tính chỉ đọc công khai ghi đè trong phần mở rộng lớp tất cả thời gian, nhưng tôi đoán tôi chưa bao giờ có nguyên nhân làm điều đó một lớp con. Tuy nhiên, trừ khi tôi đọc sai, các đoạn ở trên dường như chỉ ra rằng nó là kosher. Bất cứ ai có thể đặt tôi thẳng và/hoặc hòa giải cuộc xung đột rõ ràng giữa các tài liệu và trình biên dịch?

Tại sao tôi muốn thực hiện việc này? Tình hình thế giới thực của tôi phức tạp hơn, tất nhiên. Tôi có thể thực hiện thay đổi thiết kế để làm việc xung quanh điều này nếu cần thiết, nhưng điều này có vẻ như thay thế ma sát ít nhất (sự cần thiết phải làm điều này ở tất cả đang được thúc đẩy bởi những thay đổi khác).

Trả lời

10

Nó nói bạn có thể redeclare một tài sản readonlyreadwrite nhưng bạn đang làm ngược lại.Bạn không thể/không nên làm điều đó vì có thể thực hiện việc này:

Sub* s = [[[Sub alloc] init] autorelease]; 
Base* b = s; 
b.foo = YES; //legal for `Base` objects, but not legal for `Sub` objects 

Vi phạm the Liskov Substitution Priciple.

+0

Những gì Tom nói. Nó không có ý nghĩa để làm cho một lớp con chỉ đọc khi lớp cha cung cấp ghi đè công khai. Nói chung, bạn thêm tính đột biến đi xuống hệ thống phân cấp lớp (xem các ví dụ khác nhau không thể thay đổi -> Nhóm biến thể lớp được cung cấp trong hệ điều hành). – bbum

+0

Cảm ơn Tom và bbum. Tôi (nên) biết rõ hơn. Tôi nghĩ rằng tôi đã dành quá nhiều thời gian vào cuối tuần này để xem xét vấn đề thực tế của mình và mất đi các nguyên tắc đầu tiên. Tôi thậm chí còn có cơ hội thứ hai để bắt bản thân mình, nhưng bộ não của tôi bằng cách nào đó đã lọc ra "hoặc trong một phân lớp" trong đoạn thứ hai của doc thông qua nhiều bài đọc. Sau bữa tối và quay trở lại câu trả lời của bạn, tôi cảm thấy một chút ngớ ngẩn về điều này. Cảm ơn vì một số rõ ràng, và tôi rất thích liên kết Liskov! – Slipknot

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