为什么我们必须在Objective-C中做[MyClass类]?

dre*_*lax 44 objective-c

在Objective-C中,您可以使用以下命令调用类方法:

[MyClass aClassMethod];
Run Code Online (Sandbox Code Playgroud)

您可以使用以下命令查询实例的类型:

[someInstance isKindOfClass:[MyClass class]];
Run Code Online (Sandbox Code Playgroud)

但是,为什么我们需要做[MyClass class],而不是简单地提供MyClass这样的:

[someInstance isKindOfClass:MyClass];
Run Code Online (Sandbox Code Playgroud)

有没有理由认为编译器遇到MyClass接收器(指针类型)而不是作为参数?这是解析语言的限制吗?或者也许是编译器的限制?

bbu*_*bum 41

噢〜有趣的问题.答案是c-ism.

考虑:

@interface MyClass : NSObject
@end
@implementation MyClass
@end
Run Code Online (Sandbox Code Playgroud)

现在,说你有:

...
MyClass *m = nil;
...
Run Code Online (Sandbox Code Playgroud)

在该上下文中,编译器将其MyClass视为类型定义.该*说的变量mpointer to a hunk o' memory that contains one (or many -- don't forget your C pointer-fu) MyClass instances.

换句话说,MyClass是一种类型.

但是,在类似的情况下:

[someInstance isKindOfClass: x ];
Run Code Online (Sandbox Code Playgroud)

x必须是一个右值,或者在人类方面,必须是一个表达式的值.但是,类型不能用作右值.

[MyClass class]在语言和编译器中实际上都是一种黑客攻击,因为语法特别允许类型名称作为消息接收者(作为方法调用的目标).

而且,事实上,你可以这样做:

typedef MyClass Foo;
....
[MyClass class];
[Foo Class];
Run Code Online (Sandbox Code Playgroud)

一切都会奏效.但是,您无法执行以下操作,错误消息很明亮:

[NSUInteger class];
Run Code Online (Sandbox Code Playgroud)

错误:'NSUInteger'不是Objective-C类名或别名


现在,为什么不是特殊情况它到处都是一个裸名?

这就是类型名称和rvalues的结合,你很快就会不得不吞下像[foo isKindOfClass: (MyClass)];barfing 那样的东西[foo isKindOfClass: (MyClass *)];,然后以相当不舒服的方式侵占类型转换领域.

  • 不 - 我只知道在哪里可以改进我普遍受过良好教育的猜测.这个需要在C规范和Obj-C源中进行一些挖掘.有趣的问题. (2认同)

yeh*_*nan 7

有趣.

在Objective-C中,类名有两个角色,作为数据类型和类对象.作为数据类型名称,您可以执行以下操作:

MyClass *anObject;
Run Code Online (Sandbox Code Playgroud)

作为类对象,类名只能表示类对象作为消息接收者.这就是你必须使用的原因

... isKindOfClass:[MyClass class] ...
Run Code Online (Sandbox Code Playgroud)

但是,我不认为这是满足您需求的答案.对我来说,答案是,"是的,你想要的是合情合理的.但规范说的是另一种方式".

参考:Objective-C编程语言第32页,节:"源代码中的类名".

  • 这基本上是C兼容性的东西.接收器位置是特殊的,以允许类名,但在其他任何地方它被视为普通的C类型. (3认同)