2013-09-22 3 views
8

Во время работы над над проектом с открытым исходным кодом, я наткнулся на следующее объявление функции C и реализации:Объективные методы класса C против функций 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 

Этот пример может легко быть переписан как метод уровня класса с любой проблемы. Как бы то ни было, использование порога stringFormMimeType() требует импорта файла заголовка FSNData в любом случае.

Глядя на the Apple docs, говорится только:

Поскольку Objective-C лежит на фундаменте ANSI C, вы можете свободно смешиваться прямой код C с кодом Objective-C. Более того, ваш код может вызывать функции, определенные в программных интерфейсах, отличных от Cocoa, таких как , поскольку библиотека BSD взаимодействует в/usr/include.

Нет упоминания о том, когда функции C должны поддерживать методы Objective-C.

Единственное преимущество, которое я могу видеть на этом этапе, заключается в том, что вызов вышеуказанной функции, в отличие от метода класса, будет пропущен некоторый вызов (ы) выполнения Objective-C. В типичном случае использования FSNData это не даст заметного повышения производительности для пользователя (возможно, даже для разработчиков) *.

Какая польза существует (кроме стиля кодирования) в пользу функции C над методом класса?

* FSNData используется как часть библиотеки FSNetworking, поэтому я сомневаюсь, что в течение любого жизненного цикла приложения будут выполняться тысячи и тысячи сетевых операций.

+0

Стиль, структурирование программы (явно ассоциирование метода с классом) и небольшой (очень слабый) контроль доступа - все, о чем я могу думать. (Но я вижу, что @ipmcc упоминает наследование, и там есть несколько вещей.) –

+0

Я предпочитаю метод класса, потому что методы Objective-C предлагают именованный параметр, функции C которого не являются – onmyway133

+0

@ onmyway133 Я специально старался держаться подальше от личных предпочтений (т. е. ** кроме стиля кодирования **) и ищет техническую причину. –

ответ

7

Короче говоря, C (или C++) реализации очень полезны:

  • абстракции
  • для многократного использования
  • При изготовлении средних и больших крупномасштабных программ
  • В выполнении критических путей
  • Для реализаций «интерьера»

Какая польза существует (кроме стиля кодирования) в пользу функции C над методом класса?

  • ObjC сообщениями вводит косвенные вызовы функций.Это брандмауэры для оптимизаторов.
  • Функции C могут легко ограничивать доступ, тогда как «частные» реализации ObjC могут быть просмотрены с использованием среды выполнения ObjC или случайно переопределены.
  • Функции C могут быть удалены из вашего исполняемого файла, если они не указаны, или они могут быть закрыты. Если вы пишете многоразовый код (и вы должны), это может иметь огромное влияние на ваши двоичные размеры и время загрузки - функции C, которые не указаны/используются, могут быть удалены, но типы и методы ObjC будут сохранены (включая все, что они Справка). Вот почему бинарный размер вашего приложения может значительно возрасти, когда вы используете только небольшую часть статической библиотеки ObjC - каждый класс objc в библиотеке сохраняется. Если эта библиотека была C или C++, то вы могли бы пройти с очень небольшим ростом, потому что вам нужно только то, что упоминается. То, что ссылается или не ссылается, проще доказать с помощью C и C++.
  • Функции C могут быть встроены либо во время компиляции, либо во время фазы оптимизации времени связи.
  • Компилятор и оптимизаторы могут выполнять большую оптимизацию с помощью C-функций (например, межпроцедурные оптимизации), но очень мало с методами ObjC, потому что они всегда косвенны.
  • Чтобы избежать накладных расходов на отправку сообщений ObjC (как вы упомянули)
  • Потенциал для дополнительных операций подсчета ссылок и активности пула автозапуска при взаимодействии с объектами ObjC.

Конечно, вы не всегда будете болеть за то, что вам не нужно или используете - и помните, что методы класса ObjC также имеют некоторые преимущества над функциями C. Итак, просто посмотрите на реализации C или C++ в качестве другого инструмента в вашем наборе инструментов. Я считаю их очень полезными по мере увеличения сложности и размеров проектов, и их можно использовать для ускорения ваших программ. Просто делайте то, о чем вы в наименьшей степени сожалеете в 2015 году;)

+0

Я думаю, что ответ от @ipmcc также имеет ценную информацию. Не могли бы вы получить ссылку на то, как и когда функции будут удалены? –

+1

@ MikeD 'man strip' будет вступлением. это, используемое в сочетании с оптимизацией и правильным устранением мертвого кода (или недостижимым кодом) на разных этапах (например, компиляция, привязка), позволяет инструментам определять, что есть и что не ссылается, или недоступно для программы. это полезно для C и C++, но не относится к символам ObjC (и к тем, что они ссылаются), поскольку вы можете легко ссылаться на них динамически через среду выполнения (например, «NSClassFromString», «NSSelectorFromString»), поэтому все они сохраняются по умолчанию, потому что Xcode добавляет необходимые флаги от вашего имени. (продолжение) – justin

+1

@MikeD Функция C ссылается на ссылку, если она вызывается извне (ее можно удалить, если она включена в каждом случае), или если вы ссылаетесь на нее по адресу (например, передайте ее как указатель функции). если инструментальная цепочка понимает, что вы называете это только из недостижимого кода, тогда она также может быть устранена. я на самом деле собираюсь переписать этот бит. – justin

8

Вы уже коснулись предельной разницы в производительности, избегая вызова objc_msgSend. Методы класса Objective-C также подлежат переопределению в подклассах, поэтому реализация метода на C предотвратит его переопределение в подклассе. Соответственно, из-за этого наследования/полиморфизма времени выполнения метод Objective-C никогда не может быть встроен, тогда как функция C потенциально может быть встроена компилятором для повышения производительности.

Когда-то мне говорили, что один из мудрых людей сказал мне: «Если накладные расходы objc_msgSend слишком велики для вас, Objective-C, вероятно, является неправильным инструментом для работы».

+0

Хорошая точка о наследовании. –

Смежные вопросы