当我在Objective-C中创建@interface
时,例如:
@interface MyClass : NSObject {
@private
}
@end
编译时会成为'某事'。例如,我可以这样做:
[MyClass class]
或附加静态方法等
我无法做'meta'之类的事情,例如:
- (void)doSomethingWithInterface:(id)myInterface
{
NSLog(@"myInterface = %@", myInterface);
Class aClass = [myInterface class];
}
我可以传递一个类,但如果我可以通过界面将更清洁。那么......编译时界面会变成什么样?是否有某个文档可以解释这个问题?我可以用接口做这样的'meta'事情,或者接口的Class对象基本上可以做所有这些吗?
答案 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()
指令传递协议。
修改:更多信息
要清楚,接口只是编译器的指令。你不能去“抓住”一个界面并用它做点什么。但界面会导致一些事情发生:
+class
或其上定义的任何其他类方法);它实际上指向一个元类对象。现在,第二点可能有点令人困惑,但它也很有趣。你被告知类是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'关键字。