2013-09-22 56 views
8

Trong khi làm việc trên dự án mã nguồn mở, tôi đã xem qua phần khai báo hàm C sau đây và thực hiện:Objective C Lớp Phương pháp vs Chức năng C

// FSNData.h 
NSString *stringForMimeType(MimeType type); 

@interface FSNData : NSObject 
// All the expected objective-c property and instance method declarations 
@end 

// FSNData.m 
#import "FSNData.h" 

// where 'type' is an enum 
// this does work as expected 
NSString *stringForMimeType(MimeType type) { 
    switch (type) { 
     case MimeType_image_jpeg: return @"image/jpeg"; 
     case MimeType_image_png: return @"image/png"; 
     default: 
      NSLog(@"ERROR: FSNData: unknown MimeType: %d", type); 

     // do not return "application/octet-stream"; instead, let the recipient guess 
     // http://en.wikipedia.org/wiki/Internet_media_type 
     return nil; 
    } 
} 

@implementation 

// all properties and methods defined in FSData.h implemented as expected 

@end 

Ví dụ này có thể dễ dàng được viết lại như một phương pháp trình độ lớp với ra bất kỳ vấn đề. Do đó, mặc dù vậy, việc sử dụng bất kỳ yêu cầu stringFormMimeType() nào cũng sẽ yêu cầu nhập tệp tiêu đề FSNData.

Nhìn vào the Apple docs, nó chỉ nói:

Bởi vì Objective-C dựa trên một nền tảng của ANSI C, bạn có thể tự do intermix thẳng mã C với mã Objective-C. Hơn nữa, mã của bạn có thể gọi các hàm được định nghĩa trong các giao diện không phải là cacao lập trình, chẳng hạn như làm giao diện thư viện BSD trong/usr/include.

Không có đề cập đến thời điểm các hàm C nên ưu tiên các phương pháp Objective-C.

Lợi ích duy nhất tôi có thể thấy tại thời điểm này, là gọi hàm trên, trái với phương thức lớp, một số (các) cuộc gọi thời gian chạy Objective-C sẽ bị bỏ qua. Trong trường hợp sử dụng điển hình của FSNData, điều này sẽ không mang lại hiệu suất tăng đáng kể về hiệu suất cho người dùng (có thể ngay cả đối với nhà phát triển) *.

Lợi ích nào tồn tại (ngoài kiểu mã hóa) để ưu tiên hàm C trên phương thức lớp?

* FSNData được sử dụng như một phần của thư viện FSNetworking, vì vậy tôi nghi ngờ sẽ có hàng nghìn khi hàng nghìn hoạt động mạng được thực hiện trong suốt vòng đời của ứng dụng.

+0

Kiểu, lập cấu trúc chương trình (liên kết rõ ràng phương thức với lớp) và một chút kiểm soát truy cập (rất yếu) là tất cả những gì tôi có thể nghĩ đến. (Nhưng tôi thấy rằng @ipmcc đề cập đến thừa kế, và có một vài điều ở đó.) –

+0

Tôi thích phương thức lớp vì các phương thức Objective-C cung cấp tham số có tên, trong đó hàm C không – onmyway133

+0

@ onmyway133 Tôi đã cố gắng tránh xa từ sở thích cá nhân (ví dụ ** khác với kiểu mã hóa **) và tìm kiếm lý do kỹ thuật. –

Trả lời

7

Nói tóm lại, C (hoặc C++) triển khai là rất hữu ích:

  • Đối Abstraction
  • Đối Có thể dùng lại
  • Khi thực hiện các chương trình quy mô vừa và lớn
  • Trong thực hiện con đường quan trọng
  • Đối với triển khai 'Nội thất'

Lợi ích nào tồn tại (ngoài kiểu mã hóa) để ưu tiên hàm C trên phương thức lớp?

  • Nhắn tin ObjC giới thiệu các cuộc gọi hàm gián tiếp.Đây là tường lửa cho các trình tối ưu hóa.
  • Chức năng C có thể dễ dàng hạn chế quyền truy cập, trong khi triển khai ObjC 'riêng tư' có thể được tra cứu bằng thời gian chạy ObjC hoặc vô tình bị ghi đè.
  • Chức năng C có thể bị xóa khỏi tệp thực thi của bạn nếu không được tham chiếu hoặc có thể được đặt ở chế độ riêng tư. Nếu bạn viết mã tái sử dụng (và bạn nên), điều này có thể có tác động lớn đến kích thước nhị phân và thời gian tải của bạn - các hàm C không được tham chiếu/sử dụng có thể bị loại bỏ, nhưng các loại và phương thức ObjC sẽ được giữ nguyên (bao gồm mọi thứ chúng tài liệu tham khảo). Đây là lý do tại sao kích thước nhị phân của ứng dụng của bạn có thể tăng lên đáng kể khi bạn chỉ sử dụng một phần nhỏ của thư viện tĩnh ObjC - mọi lớp objc trong thư viện đều được giữ nguyên. Nếu thư viện đó là C hoặc C++, thì bạn có thể đạt được với sự tăng trưởng rất nhỏ bởi vì bạn chỉ cần những gì được tham chiếu. Những gì được hoặc không được tham chiếu là dễ dàng hơn để chứng minh với C và C++.
  • Các hàm C có thể được gạch chân, trong khi biên soạn hoặc trong giai đoạn Tối ưu hóa thời gian liên kết.
  • Trình biên dịch và trình tối ưu hóa có thể thực hiện tối ưu hóa nhiều chức năng C (ví dụ: tối ưu hóa liên thủ tục), nhưng rất ít với phương pháp ObjC vì chúng luôn gián tiếp.
  • Để tránh phí gửi tin nhắn ObjC (như bạn đã đề cập)
  • Tiềm năng cho hoạt động đếm tham chiếu bổ sung và hoạt động tự động phát hành nhóm khi tương tác với đối tượng ObjC.

Tất nhiên bạn sẽ không phải lúc nào cũng làm tổn thương cho những thứ bạn không cần hoặc sử dụng - và nhớ rằng phương thức lớp ObjC cũng có một số lợi ích đối với các hàm C. Vì vậy, chỉ cần nhìn vào việc triển khai C hoặc C++ như một công cụ khác trong hộp công cụ của bạn. Tôi thấy chúng rất hữu ích vì sự phức tạp và kích thước dự án tăng lên, và chúng có thể được sử dụng để làm cho các chương trình của bạn nhanh hơn nhiều. Chỉ cần làm những gì bạn ít có khả năng hối tiếc trong năm 2015;)

+0

Tôi nghĩ câu trả lời của @ipmcc cũng có thông tin giá trị. Bạn có thể có một liên kết cho các chức năng như thế nào và khi nào bị tước bỏ? –

+1

@MikeD 'man strip' sẽ là phần giới thiệu. điều này, được sử dụng kết hợp với tối ưu hóa và loại bỏ mã chết thích hợp (hoặc mã không thể truy cập) ở các giai đoạn khác nhau (ví dụ: biên dịch, liên kết) cho phép các công cụ xác định nội dung là gì và những gì không được tham chiếu hoặc chương trình không thể truy cập. điều này rất hữu ích cho C và C++, nhưng không áp dụng cho các ký hiệu ObjC (và những gì chúng tham chiếu) vì bạn có khả năng dễ dàng tham chiếu chúng một cách linh động qua thời gian chạy (ví dụ 'NSClassFromString',' NSSelectorFromString'), mặc định vì Xcode thêm các cờ cần thiết thay cho bạn. (tiếp theo) – justin

+1

@MikeD một hàm C được 'tham chiếu' nếu nó được gọi là bên ngoài (nó có thể bị loại bỏ nếu được nêu trong mọi trường hợp), hoặc nếu bạn tham chiếu nó theo địa chỉ (ví dụ: chuyển nó như một con trỏ hàm). nếu toolchain nhận ra rằng bạn gọi nó chỉ từ mã không thể truy cập, thì nó cũng có thể bị loại bỏ. Tôi thực sự sẽ tua lại bit đó. – justin

8

Bạn đã chạm vào chênh lệch hiệu suất cận biên của việc tránh cuộc gọi objc_msgSend. Các phương thức lớp Objective-C cũng phụ thuộc vào trọng số trong các lớp con, do đó việc thực hiện một phương thức trong C sẽ ngăn không cho nó bị ghi đè trong một lớp con. Có liên quan, vì tính kế thừa/đa hình thời gian chạy đó, một phương thức Objective-C không bao giờ có thể được inlined, trong khi một hàm C có khả năng được trình biên dịch inlined cho hiệu năng được thêm vào.

Khi nói đến việc tránh objc_msgSend, một người khôn ngoan đã từng nói với tôi, "Nếu chi phí của objc_msgSend quá lớn đối với bạn, Mục tiêu-C có thể là công cụ sai cho công việc".

+0

Điểm tốt về thừa kế. –

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