2013-03-09 28 views
9

Nhìn vào mã nguồn thư viện runtime Objective-C, đặc biệt là tại objc-runtime-new.mm, tôi đã thấy một số hàm và thậm chí cả các chú thích được gọi là các lớp lười và không lười. Dường như các lớp không có phương thức +load được gọi là các lớp lười, nhưng tôi không chắc chắn về điều đó và rất có thể là không đúng. Sau khi tìm kiếm trên Google, tôi không tìm thấy gì về các lớp học lười biếng trên Objective-C.Mục tiêu-C: Lớp học lười biếng là gì?

Vì vậy, một lớp học lười biếng trong Mục tiêu-C là gì? Obj-C có tính năng này không? Nó có liên quan đến sự hiện diện của phương pháp +load trong việc triển khai lớp không? Tại tệp được liên kết ở trên, hệ thống thời gian chạy gọi hàm _getObjc2NonlazyClassList để nhận danh sách các lớp không lười từ một hình ảnh. Tại sao không có chức năng _getObjc2LazyClassList?

+0

có thể là một lớp được tải từ plugin. có thể kiểm tra tài liệu về plugin/dyld/mã được nạp động – nielsbot

+0

Bạn có chắc chắn điều đó có nghĩa là lớp học lười biếng và không chỉ là danh sách? –

+0

Tôi đồng ý với @JoshCaswell, cho rằng sau này trong nguồn thời gian chạy có tham chiếu đến việc tải nhẹ nhàng trong các lớp học. Nó gần như chắc chắn đề cập đến danh sách, chứ không phải là một lớp học là 'lười biếng'. – lxt

Trả lời

11

Tôi đã tìm thấy câu trả lời: Đó là tất cả về một lớp thực hiện hoặc không phải là phương pháp +load.

Tất cả các lớp được triển khai trong một tệp hình ảnh nhất định có tham chiếu trong danh sách được lưu trữ trong phần nhị phân của "__DATA, __objc_classlist, regular, no_dead_strip".Danh sách này cho phép hệ thống thời gian chạy theo dõi tất cả các lớp được lưu trữ trong tệp đó. Tuy nhiên, không phải tất cả các lớp cần được thực hiện khi chương trình khởi động. Đó là lý do tại sao khi một lớp thực hiện phương thức +load, nó cũng có tham chiếu trong danh sách được lưu trữ trong phần "__DATA, __objc_nlclslist, regular, no_dead_strip".

Vì vậy, _getObjc2NonlazyClassList truy xuất danh sách các lớp thực hiện phương thức +load và được gọi là không lười. _getObjc2ClassList truy xuất danh sách tất cả các lớp trong tệp hình ảnh, bao gồm các lớp không có phương thức +load (và được gọi là lười) và các lớp không lười. Các lớp học không lười biếng phải được thực hiện khi chương trình khởi động. Các lớp học lười biếng, mặt khác, không cần phải được thực hiện ngay lập tức. Điều này có thể bị trì hoãn cho đến khi lớp học nhận được một tin nhắn lần đầu tiên, ví dụ (đó là lý do cho họ được coi là "lười biếng").

Điều tương tự cũng đúng với các danh mục.

+0

Chỉ cần lưu ý rằng đối với các danh mục, bạn phải sử dụng cờ liên kết 'all_load' nếu các danh mục đó nằm trong thư viện bên ngoài. –

+0

Điều này có thể gần như chính xác, nhưng tôi đã nhìn thấy hình ảnh Macho có chứa một __objc_nlclslist, nhưng không chứa một phần __objc_classlist. – jsears

5

"Lười biếng" được sử dụng trong hai ngữ cảnh khác nhau.

Đầu tiên, khi phê bình một thiết kế lớp, lập luận rằng một lớp là không hiệu quả - rằng nó không đủ để biện minh cho sự tồn tại của nó. Mọi người cũng gọi loại này là "mỏng". Đây có thể không phải là ý của bạn ở đây.

Thứ hai, lười biếng đánh giáinstantiation lười biếng có nghĩa là lớp chỉ thực hiện công việc đánh giá một tài sản hoặc khởi tạo riêng của mình khi thực sự cần thiết.

Ví dụ: giả sử chúng tôi có một lớp tạo đối tượng nhân viên.

@implementation Employee 
- (id) initWithID: (IdentificationCode*) ident 
{ 
    self =[super init] 
    if (self) { 
     _records=[self retrieveEmployeeRecordsFor: ident]; 
     _identification=ident; 
     } 
    return self; 
} 

Điều này là tốt, nhưng truy xuất tất cả các bản ghi từ cơ sở dữ liệu có thể chậm. Và đôi khi chúng ta không cần phải làm công việc. Ví dụ:

- (BOOL) isFounder 
{ 
    if (indent.number<10) return YES; 
    return NO; 
} 

Nếu chúng tôi khởi tạo Nhân viên chỉ đơn giản là tìm hiểu xem họ là Người sáng lập, chúng tôi không cần tra cứu hồ sơ của họ!

..... 
if ([thisEmployee isFounder]) { 
     [self sendCandyTo: thisEmployee.identification]; 
     } 

Mặt khác, đôi khi chúng ta cần đến chúng:

- (NSArray*) payments 
{ 
    return [self.records retrievePayStubs]; 
    } 

Vì vậy, nếu chúng ta đang xây dựng một nhân viên chỉ để gọi isFounder, chúng ta lãng phí một tra cứu cơ sở dữ liệu. Nhưng chúng ta không thể bỏ qua điều đó, bởi vì payments cần nó.

Những gì chúng tôi làm là lấy tra cứu cơ sở dữ liệu ra khỏi hàm tạo và đặt nó theo phương thức load.

- (void) load 
{ 
    if (records) return; 
    self.records=[self retrieveEmployeeRecordsFor: ident]; 
} 

- (NSArray*) payments 
{ 
    [self load]; 
    return [self.records retrievePayStubs]; 
    } 

Bây giờ, chúng tôi chỉ tải hồ sơ nhân viên khi chúng tôi thực sự cần chúng. Nếu chúng đã được tải, chúng tôi không thực hiện thêm bất kỳ công việc nào (ngoài một cuộc gọi phương thức). Nếu chúng ta không bao giờ cần các hồ sơ thanh toán, thì chúng ta không cần phải làm công việc gì cả.

Lớp học chỉ hoạt động khi cần - và đợi đến phút cuối cùng để thực hiện công việc. Đó là "lười biếng!"

+0

Cảm ơn bạn đã trả lời, Mark. Đó là những gì tôi tưởng tượng. Vì vậy, một lớp học được coi là "lười biếng" vì hành vi của nó. Nhưng một cái gì đó vẫn làm phiền tôi: sự tồn tại của hàm '_getObjc2NonlazyClassList' có vẻ như nạp các lớp được lưu trữ dưới dạng không lười trong tệp hình ảnh. Nó giống như có một khía cạnh mà làm cho một lớp không lười biếng tại thời gian biên dịch. Hoặc có lẽ nó chỉ là danh pháp: tất cả các lớp được tải từ một tệp hình ảnh được coi là không lười ... – LuisABOL

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