Заголовок / основные файлы в Objective C - PullRequest
2 голосов
/ 26 марта 2012

Я читаю о программировании на iOS и купил книгу «Программирование на iOS 4».Есть вводная часть, где среди нескольких вещей упоминается «Файлы».

Я не понимаю, как составить исходные файлы.У вас есть файл заголовка с объявлениями функций, затем у вас есть соответствующий файл с определениями функций.

Допустим, у вас есть Car.h и Car.m & Person.h и Person.m.

Теперь, если вы хотите использовать Car в классе Person, вы должны импортировать только файл Car.h.Как этого достаточно?Я не понимаю последовательность, которую он составляет и создает программу.(Не думая о технических вещах, просто файлы h / m.)

Ответы [ 5 ]

4 голосов
/ 26 марта 2012
  • .h или «файл заголовка» содержит интерфейс.
  • .m или «файл реализации» содержит реализацию.

Каждый файл реализациитакже называется «модулем компиляции», потому что компилятор компилирует каждый из них отдельно.В каждом модуле компиляции компилятор должен знать о типах и методах.Все, что нужно знать о классе для создания правильного кода, - это информация о методах, которые он реализует.

Итак, давайте представим, что у вас есть эти файлы:

Car.h

#import <Foundation/Foundation.h>

@interface Car : NSObject
- (void)drive;
@end

Car.m

#import "Car.h"

@implementation Car

- (void)drive {
    NSLog(@"I'm driving!");
}

@end

Person.h

#import <Foundation/Foundation.h>

@class Car;

@interface Person : NSObject

@property (nonatomic, strong) Car *car;

- (void)start;

@end

Person.m

#import "Person.h"
#import "Car.h"

@implementation Person

@synthesize car;

- (void)start {
    [car drive];
}

@end

Теперь, когда компилятор работает, он компилирует обаCar.m и Person.m в Car.o и Person.o соответственно.[Затем они попадают в окончательный двоичный файл, но это пока выходит за рамки этого вопроса].

Когда он компилирует Person.m, компилятору не нужно знать, как - (void)drive из Car реализован, но ему нужно знать, что он существует, что это метод, который не принимает аргументов и ничего не возвращает.Он не заботится о реализации, просто он существует .Так что вам просто нужно #import файл заголовка Car, чтобы сообщить компилятору о методах, существующих в Car.Компилятор знает, что реализация существует, потому что вы сказали об этом, а затем компоновщик сделает свое дело, чтобы правильно подключить вызов метода к правильной реализации.Как линкер на самом деле это делает, это огромная тема, и я призываю вас пойти и прочитать об этом отдельно, если вы этого еще не поняли.

Обратите внимание, что это одинаково для всех стандартных NS классов.которые вы используете, такие как NSObject, NSString и т. д. Вам просто нужно #import Foundation.h из Foundation фреймворка, который сообщает компилятору о том, что это за классы и какие методы для них определены.

3 голосов
/ 26 марта 2012

Создание исполняемого файла из набора файлов исходного кода представляет собой двухэтапный процесс.

Во-первых, все файлы .m по отдельности компилируются с помощью компилятора Objective-C.Это превращает каждый файл в .o файл, который является файлом объектного кода.Однако, если код в файле .m ссылается на вещи, определенные в других файлах .m, компилятор не знает об этом, поэтому он просто оставляет неразрешенные ссылки в файле .o.

Второй этап называется связыванием.Это берет все файлы .o и объединяет их в исполняемый файл.Когда компоновщик находит неразрешенные ссылки в одном файле .o, он проверяет все остальные для разрешения ссылки.

Заголовочные файлы позволяют компилятору получать некоторую информацию из-за пределов конкретного .m файла, который он компилирует в настоящее время.,Поэтому, если у вас есть два класса Foo и Bar, они условно определены в файлах Foo.m и Bar.m Чтобы компилятор знал, как выглядит класс Bar при компиляции Foo.m, мы помещаем классBar s объявление интерфейса в заголовочном файле (обычно Bar.h) и импортирование его в ваш .m файл.Если вы видите строку

#import "Bar.h"

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

1 голос
/ 26 марта 2012

Какой язык вы использовали до сих пор? Многие языки делают это таким образом, включая c и c ++. Файлы m скомпилированы в реальную программу, а файлы h предоставляют список способов взаимодействия с ней. Хотя вы все равно можете вызывать методы, если взаимодействуете с целевой средой выполнения c, компилятор не гарантирует их существование, если они не находятся в файле h.

Теперь я говорю «гарантия», но если вы не предоставите реализацию в файле m, брат и компилятор, компоновщик будет соответствовать. Он попытается перейти в другой m-файл, основываясь на своем h-файле, только для трагического обнаружения, что его там нет.

Преимущества такого разделения заключается в том, что вы можете скомпилировать ваш исходный код в библиотеку и распространять его вместе с файлами h, а другое приложение может использовать его без исходного кода реализации.

В итоге, m-файлы компилируются в потерянный остров битов, а h-файлы - это карта, чтобы обойти это. Если на карте чего-то не существует, вы потеряетесь. Если что-то существует, но отсутствует на карте, у вас будет много проблем с его поиском.

0 голосов
/ 26 марта 2012

Компилятор справится с этим за вас.

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

0 голосов
/ 26 марта 2012

Заголовочные файлы указывают, какие сообщения («методы» на других языках) могут быть переданы в класс.Это все, что нужно знать компилятору для компиляции вашего кода;компоновщик в конечном итоге соединит все, так сказать, с помощью файлов *.m.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...