Что такое @interface, скомпилированный в Objective-C? - PullRequest
2 голосов
/ 24 апреля 2011

Когда я создаю @interface в Objective-C, например:

@interface MyClass : NSObject {
   @private

}
@end

Он становится «чем-то» при компиляции.Например, я могу сделать:

[MyClass class]

Или прикрепить статические методы и т. Д.

Я не могу сделать что-то «мета», например:

- (void)doSomethingWithInterface:(id)myInterface
{
    NSLog(@"myInterface = %@", myInterface);
    Class aClass = [myInterface class];
}

Iможет передать класс, но было бы чище, если бы я мог просто передать интерфейс.Итак ... чем становится интерфейс при компиляции?Есть ли документ, который объясняет это где-то?Могу ли я делать такие "мета" вещи с интерфейсами, или объект класса интерфейса по существу делает все это?

Ответы [ 3 ]

2 голосов
/ 24 апреля 2011

Уверен, вы не понимаете, что такое интерфейс в Objective-C.Интерфейс - это просто объявление типа данных и методов класса.Протокол Objective-C, аналогичный Java-интерфейсам, - это протокол.

«Конечно, я мог бы пропустить класс…». Вы только что ответили на свой вопрос.Потому что интерфейс создает его класс!Итак,

- (void)doSomethingWithClass:(Class)aClass {
  NSLog(@"class == %@", aClass);
}

Передайте что-нибудь в это, используя

[obj doSomethingWithClass:[obj class]];

Если вы действительно хотели сказать, что хотите передавать протоколы, вот что вы делаете.Предполагая, что у вас есть протокол, который выглядит как

@protocol Foldable <NSObject>
+ (id <Foldable>)unit;
- (id <Foldable>)append:(id <Foldable>)object;
@end

Затем вы можете делать с ним что-то вроде этого:

- (void)doSomethingWithProtocol:(Protocol *)aProtocol {
  NSLog(@"protocol == %s", protocol_getName(aProtocol));
}

Протокол можно передать в этот метод следующим образом:

[obj doSomethingWithProtocol:@protocol(Foldable)];

Как видите, в то время как вы передаете классы, отправляя +class идентификатору типа Objective-C, вы передаете протоколы, используя директиву @protocol().

Редактировать: Дополнительная информация

Для ясности, интерфейс - это просто инструкция для компилятора.Вы не можете пойти и "захватить" интерфейс и сделать что-то с ним.Но интерфейс вызывает несколько вещей:

  1. Он вызывает создание структуры внутри вашей скомпилированной программы;в этой структуре есть переменные экземпляра вашего класса, а также переменные его суперклассов.
  2. Это заставляет имя типа, связанное с этой структурой, принимать сообщения Objective-C (например, +class или любые другие).метод класса, определенный на нем);на самом деле он указывает на объект метакласса.

Теперь вторая точка зрения может показаться запутанной, но это также довольно интересно.Вам сказали, что классы являются объектами в Objective-C, что в основном правильно.Но это может привести вас к удивлению, почему следующее невозможно:

[self doSomethingWithClass:NSObject];

Причина, по которой вы не можете сделать это, та же самая причина, по которой вы не можете ожидать, что что-то подобное будет работать:

[self doSomethingWithType:int];

Поскольку оказывается, что идентификаторы классов (например, NSObject) на самом деле являются просто именами структурных типов, но с изюминкой: они также могут получать сообщения.Следовательно, если вы используете класс Objective C в качестве параметра шаблона в C ++, вы действительно можете отправлять ему сообщения!

template <typename T>
void something_crazy() {
  NSLog(@"object: %@", [[T new] autorelease]);
}

something_crazy<NSArray>();

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

0 голосов
/ 24 апреля 2011

Классы - это объекты, поэтому вы можете сказать:

Class *someClass = [myObject class];

Теперь someClass - это указатель на класс, членом которого является myObject. Вы можете написать

[foo doSomethingWithClass:someClass];

и вы передаете сам класс - то, что создается при компиляции раздела @interface SomeClass : NSObject....

Как кто-то сказал ранее, не путайте директиву Obinter-C @interface с интерфейсами Java. Протоколы Objective-C аналогичны интерфейсам Java; @interface аналогичен ключевому слову Java 'class'.

0 голосов
/ 24 апреля 2011

Интерфейс - это интерфейс к классу. Так что это диктует многие свойства названного класса. Интерфейсы не являются отдельными объектами; есть явное отображение 1: 1 между интерфейсами и классами. Так что мне неясно, чего вы пытаетесь достичь. Можете ли вы объяснить, почему вы думаете, что было бы чище передавать интерфейсы?

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

РЕДАКТИРОВАТЬ: Я думаю, что теперь я понимаю вас лучше (извинения за мое медленное поглощение). Вы говорите, что дано что-то вроде:

@interface SomeClass
{
    // ...whatever...
}

// ... whatever...

@end

/* Elsewhere: */
- (void)doThingWithClass:(Class)class
{
   // do something
}

Вы не понимаете, почему вы должны использовать:

[instanceOfSomething doThingWithClass:[SomeClass class]];

Вместо:

[instanceOfSomething doThingWithClass:SomeClass];

Причина в том, что SomeClass не является абстрактным символом, понятным только компилятору во время компиляции, это фактический экземпляр класса (технически это метакласс), присутствующий в памяти во время выполнения. Вот как работают методы класса, например

[SomeClass doSpecialThing];

Или:

[NSString stringWithString:@"someString"];

Компилятор не может просто догадаться, что вы имеете в виду класс, а не экземпляр. Таким образом, вы используете сообщение «Class», чтобы получить класс из экземпляра. Возможно, это объяснение (Какао с любовью "Что такое мета-класс в Objective C?") Поможет.

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