什么是在Objective-C中编译成的@interface?

时间:2011-04-23 20:17:03

标签: objective-c

当我在Objective-C中创建@interface时,例如:

@interface MyClass : NSObject {
   @private

}
@end

编译时会成为'某事'。例如,我可以这样做:

[MyClass class]

或附加静态方法等

我无法做'meta'之类的事情,例如:

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

我可以传递一个类,但如果我可以通过界面将更清洁。那么......编译时界面会变成什么样?是否有某个文档可以解释这个问题?我可以用接口做这样的'meta'事情,或者接口的Class对象基本上可以做所有这些吗?

3 个答案:

答案 0 :(得分:2)

很确定你对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. 它会导致在已编译的程序中生成结构;这个struct有你的类的实例变量,以及它的超类的实例变量。
  2. 它使与该结构相关联的类型名称能够接受Objective-C消息(如+class或其上定义的任何其他类方法);它实际上指向一个元类对象。
  3. 现在,第二点可能有点令人困惑,但它也很有趣。你被告知类是Objective-C中的对象,这大多是正确的。但这可能会让你想知道为什么以下是不可能的:

    [self doSomethingWithClass:NSObject];
    

    您无法做到这一点的原因与您不能指望以下内容相同的原因:

    [self doSomethingWithType:int];
    

    因为事实证明类标识符(如NSObject)实际上只是结构类型名称,但有一个扭曲:它们也可以接收消息。因此,如果您在C ++中使用Objective-C类作为模板参数,您实际上可以向其发送消息!

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

    这是回答上一个问题的一种非常冗长的方式,编译后界面变成了什么类型。 接口不会本身在编译后成为任何时间或任何时间,但会导致生成一种特殊的pimped结构,它接受充当元类的消息。 / p>

答案 1 :(得分:0)

接口是类的接口。因此它决定了命名类的许多属性。接口不是单独的实体;接口和类之间有一个明确的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”消息从实例中获取类。可能this explanation(Cocoa with Love's“Objective C中的元类是什么?”)会有所帮助。

答案 2 :(得分:0)

类是对象,所以你可以说:

Class *someClass = [myObject class];

现在,someClass是指向myObject所属类的指针。你可以写

[foo doSomethingWithClass:someClass];

你正在传递类本身 - 编译@interface SomeClass : NSObject...部分时创建的东西。

如前所述,不要将Objective-C的@interface指令与Java接口混淆。 Objective-C的协议类似于Java的接口; @interface类似于Java的'class'关键字。