2009-09-03 27 views
5

Dựa trên một số câu trả lời cho this question có vẻ như + phân bổ thực hiện một số phép thuật hậu trường để cấp phát bộ nhớ cho một thể hiện của đối tượng trong Mục tiêu-C. Có bao giờ cần phải ghi đè + phân bổ không?Có bao giờ cần một lớp để ghi đè + phân bổ trong Objective-C không?

+0

gì Ken nói. Nhưng ... để nhấn mạnh ... nó là cực kỳ hiếm hoi để làm như vậy. – bbum

Trả lời

7

Khá hiếm.

NSString là ví dụ về lớp ghi đè + phân bổ dưới dạng chi tiết triển khai. Nếu bạn đã kiểm tra, bạn sẽ tìm thấy + [NSString alloc] trả về một cái gì đó của lớp NSPlaceholderString. Đây là một phần của việc thực hiện chuỗi class cluster.

Bạn cũng có thể ghi đè để phân bổ từ một phân bổ NSZone khác nhau làm mặc định. Hoặc, bạn có thể chơi các thủ thuật như gọi số NSAllocateObject với một số khác không cho extraBytes để cung cấp lượng không gian động sau các thanh ngang của bạn. Ví dụ: bạn có thể nghĩ rằng lớp con riêng tư của NSString mà bạn thường kết thúc sẽ trông giống như sau:

@interface { 
    NSUInteger length; 
    unichar *data; 
} 

nhưng điều đó không đúng. Đó là một khối bộ nhớ chứa cả độ dài và dữ liệu ký tự. Các cá thể NSString khác nhau là các khối kích thước bộ nhớ khác nhau. Đây là loại điều bạn có thể sắp xếp bằng cách gọi trực tiếp NSAllocateObject.

Nhưng tất cả những điều này là thủ thuật và hack. Nếu bạn ghi đè + phân bổ, điều gì đó đặc biệt đang diễn ra.

4

+alloc không thực hiện bất kỳ phép thuật nào, nó chỉ gọi một phương thức trong thời gian chạy Objective-C để lấy kích thước của một cá thể lớp và phân bổ số lượng bộ nhớ đó. Bạn có thể muốn ghi đè +alloc khi viết một singleton thực (nghĩa là bạn muốn đảm bảo rằng chỉ có một phiên bản lớp học của bạn có thể được phân bổ). Mặc dù hiếm khi cần thiết để đi đến độ dài này khi viết một lớp đơn, bạn có thể. Nói chung, bạn sẽ ghi đè lên +alloc để cung cấp thay thế (như không cấp phát bộ nhớ trong vùng khác, phân bổ lớp khác với lớp nhận - hành vi này có thể làm gì) hoặc bạn có thể gọi +[super alloc] để thực hiện công việc chuẩn rồi thêm các tùy chỉnh của riêng bạn.

1

tôi ghi đè alloc cho các lớp Singleton, ví dụ .:

#import "Singleton.h" 

static Singleton * instance; 

@implementation Singleton 

+ (void)initialize 
{ 
    if (!instance) { 
     instance = [[super allocWithZone:NULL] init]; 
    } 
} 

+ (id)allocWithZone:(NSZone * const)notUsed 
{ 
    return instance; 
} 

@end 
+0

Đây thường không phải là cách thích hợp để làm điều đó, bởi vì bạn hiểu sai người dùng viết '[Singleton new] 'mà họ sẽ không nhận được một phiên bản mới. Trong thực tế, cá thể có 'init'-ed hai lần thay vì một lần. Thay vào đó, bạn chỉ nên trưng ra một phương thức 'class \ classInstance' + (instancetype); Và bảo vệ 'allocWithZone:' sẽ không bảo vệ bạn khỏi người dùng bằng cách sử dụng các hàm thời gian chạy để khởi tạo nhiều phiên bản. –

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