为什么我们要在Objective-C中做MyClass类?

时间:2021-09-07 00:26:53

In Objective-C, you can invoke class methods with:

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

[MyClass aClassMethod];

And you can query an instance's kind with:

你可以查询一个实例的类型:

[someInstance isKindOfClass:[MyClass class]];

But, why do we need to do [MyClass class], and not simply provide MyClass like this:

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

[someInstance isKindOfClass:MyClass];

Is there a reason that the compiler is fine with encountering MyClass as a receiver (a pointer type) but not as an argument? Is it a limitation of parsing the language? Or perhaps a limitation of the compiler?

编译器是否可以将MyClass作为接收者(指针类型)而不是作为参数来使用?这是解析语言的局限性吗?或者是编译器的限制?

8 个解决方案

#1


41  

Ooooh... fun question. The answer is a c-ism.

唔……有趣的问题。答案是c主义。

Consider:

考虑:

@interface MyClass : NSObject
@end
@implementation MyClass
@end

Now, say you have:

现在,你说:

...
MyClass *m = nil;
...

In that context, the compiler sees MyClass as a type definition. The * says that the variable m is a pointer to a hunk o' memory that contains one (or many -- don't forget your C pointer-fu) MyClass instances.

在该上下文中,编译器将MyClass视为类型定义。*表示变量m是指向一个包含一个(或多个——不要忘记您的C pointerfu) MyClass实例的hunk o内存的指针。

In other words, MyClass is a type.

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

But, in the context of something like:

但是,在这样的背景下

[someInstance isKindOfClass: x ];

x must be an rvalue or, in human terms, the value of an expression. A type, however, cannot be used as an rvalue.

x必须是一个rvalue,或者用人类的术语来说,是表达式的值。但是,类型不能作为rvalue使用。

That [MyClass class] works is actually a bit of a hack, both in the language and the compiler in that the grammar specifically allows a type name to be the message receiver (to be the target of a method call).

[MyClass类]起作用实际上是一种技巧,在语言和编译器中都是如此,因为语法特别允许类型名作为消息接收者(成为方法调用的目标)。

And, as a matter of fact, you can do:

事实上,你可以这样做:

typedef MyClass Foo;
....
[MyClass class];
[Foo Class];

It'll all work. However, you can't do the following but the error message is illuminating:

它将所有的工作。但是,您不能执行以下操作,但是错误消息具有启发性:

[NSUInteger class];

error: ‘NSUInteger’ is not an Objective-C class name or alias

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


Now, why not special case it everywhere as a bare name?

现在,为什么不把它作为一个普通的名字呢?

That colludes type names and rvalues and you quickly end up having to swallow something like [foo isKindOfClass: (MyClass)]; while barfing on [foo isKindOfClass: (MyClass *)]; which then encroaches upon typecasting territory in a rather uncomfortable fashion.

这样就把名称和值合并在一起,你很快就得吞下一些东西,比如[foo isKindOfClass: (MyClass)];在[foo isKindOfClass: (MyClass *)]上barfing;然后以一种相当不舒服的方式侵占了类型化领域。

#2


7  

Interesting.

有趣。

In Objective-C, class name has two roles, as a data type and as a class object. As a data type name, you can do things like:

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

MyClass *anObject;

As a class object, the class name can stand for the class object only as a message receiver. And this is why you have to use

作为类对象,类名只能作为消息接收方表示类对象。这就是为什么要用

... isKindOfClass:[MyClass class] ...

However, I don't think this is the answer which can satisfy your need. To me, the answer is, "yes, what you want is plausible. But the spec says the other way".

但是,我不认为这就是你所需要的答案。对我来说,答案是:“是的,你想要的是合理的。”但规格说明却相反。

Reference: The Objective-C Programming Language Page 32, section: "Class Names in Source Code".

参考:Objective-C编程语言第32页,部分:“源代码中的类名”。

#3


2  

@John and @ryanprayogo -- you are both fundamentally wrong. MyClass is a Class, which is also an object, but does not inherit from NSObject. Objective-C is kind of weird this way, but its actually brilliant when fully explained (See here). The answer here, though, is as @yehnan said, that a class name can be either a type name for declarators and casts, or as a receiver for messages. The implementation of [MyClass class] returns self (which is, within the method, MyClass). Also as @yehnan said, the language could support passing it as an argument, although it simply doesn't.

@John和@ryanprayogo——你们俩从根本上都是错误的。MyClass是一个类,也是一个对象,但不从NSObject继承。Objective-C有点奇怪,但是当完全解释的时候它确实很精彩(见这里)。不过,这里的答案正如@yehnan所说,类名可以是声明者和类型转换的类型名,也可以是消息的接收者。[MyClass]的实现返回self(在方法中是MyClass)。同样,正如@yehnan所说,语言可以支持将它作为一个参数传递,尽管它只是不支持。

#4


1  

My first glance answer is because [MyClass class] return a object of type Class, and MyClass doesn't inherit from Class...

我的第一个答案是,因为[MyClass类]返回一个类类型的对象,而MyClass不从类继承……

#5


1  

@yehnan captures it well, but I'll expand on this a little. Yes, the compiler could be modified to automatically convert a class identifier into its applicable Class in places where it is an argument rather than only when it is the target of a message. But there's not a lot of call for that kind of added complexity in the compiler (translated: slower, harder to detect coding errors). You shouldn't be calling things that return Class very often. If you are, then your object model is broken. Class-checking should be the last, desperate approach after everything else has failed (most notably correct typing and then respondsToSelector:). So for this kind of rare event, it doesn't make a lot of sense to complicate the compiler this way.

@yehnan很好地抓住了这一点,但我还是要稍微扩展一下。是的,可以对编译器进行修改,以便在作为参数的地方自动将类标识符转换为其适用的类,而不是仅当它是消息的目标时。但是在编译器中并没有太多的要求增加这种复杂性(换句话说:更慢,更难检测编码错误)。你不应该经常调用返回类的东西。如果是,那么对象模型就被破坏了。类检查应该是所有其他方法失败后的最后一种绝望的方法(最值得注意的是,正确输入然后respondsToSelector:)。所以对于这种罕见的事件,用这种方式使编译器复杂化并没有多大意义。

#6


-1  

Because what the isKindOfClass expects is a "class" and that's what get returned from invoking: [MyClass class]

因为isKindOfClass期望的是一个“类”,这就是从调用返回的结果:[MyClass类]

#7


-1  

I'm thinking that MyClass is actually a meta-class. You send it the class message to get the actual class (of type Class).

我认为MyClass实际上是一个元类。您将类消息发送给它以获取实际的类(类型类)。

#8


-2  

MyClass is not of type Class.

MyClass不是类型类。

[MyClass class] is of type Class.

[MyClass类]是类型类。

If you are familiar with Java, the concept is the same.

如果您熟悉Java,概念是一样的。

java.lang.String is not of type java.lang.Class

. lang。String不是java.lang.Class类型

java.lang.String.getClass() is of type java.lang.Class

getclass()类型为java.lang.Class

#1


41  

Ooooh... fun question. The answer is a c-ism.

唔……有趣的问题。答案是c主义。

Consider:

考虑:

@interface MyClass : NSObject
@end
@implementation MyClass
@end

Now, say you have:

现在,你说:

...
MyClass *m = nil;
...

In that context, the compiler sees MyClass as a type definition. The * says that the variable m is a pointer to a hunk o' memory that contains one (or many -- don't forget your C pointer-fu) MyClass instances.

在该上下文中,编译器将MyClass视为类型定义。*表示变量m是指向一个包含一个(或多个——不要忘记您的C pointerfu) MyClass实例的hunk o内存的指针。

In other words, MyClass is a type.

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

But, in the context of something like:

但是,在这样的背景下

[someInstance isKindOfClass: x ];

x must be an rvalue or, in human terms, the value of an expression. A type, however, cannot be used as an rvalue.

x必须是一个rvalue,或者用人类的术语来说,是表达式的值。但是,类型不能作为rvalue使用。

That [MyClass class] works is actually a bit of a hack, both in the language and the compiler in that the grammar specifically allows a type name to be the message receiver (to be the target of a method call).

[MyClass类]起作用实际上是一种技巧,在语言和编译器中都是如此,因为语法特别允许类型名作为消息接收者(成为方法调用的目标)。

And, as a matter of fact, you can do:

事实上,你可以这样做:

typedef MyClass Foo;
....
[MyClass class];
[Foo Class];

It'll all work. However, you can't do the following but the error message is illuminating:

它将所有的工作。但是,您不能执行以下操作,但是错误消息具有启发性:

[NSUInteger class];

error: ‘NSUInteger’ is not an Objective-C class name or alias

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


Now, why not special case it everywhere as a bare name?

现在,为什么不把它作为一个普通的名字呢?

That colludes type names and rvalues and you quickly end up having to swallow something like [foo isKindOfClass: (MyClass)]; while barfing on [foo isKindOfClass: (MyClass *)]; which then encroaches upon typecasting territory in a rather uncomfortable fashion.

这样就把名称和值合并在一起,你很快就得吞下一些东西,比如[foo isKindOfClass: (MyClass)];在[foo isKindOfClass: (MyClass *)]上barfing;然后以一种相当不舒服的方式侵占了类型化领域。

#2


7  

Interesting.

有趣。

In Objective-C, class name has two roles, as a data type and as a class object. As a data type name, you can do things like:

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

MyClass *anObject;

As a class object, the class name can stand for the class object only as a message receiver. And this is why you have to use

作为类对象,类名只能作为消息接收方表示类对象。这就是为什么要用

... isKindOfClass:[MyClass class] ...

However, I don't think this is the answer which can satisfy your need. To me, the answer is, "yes, what you want is plausible. But the spec says the other way".

但是,我不认为这就是你所需要的答案。对我来说,答案是:“是的,你想要的是合理的。”但规格说明却相反。

Reference: The Objective-C Programming Language Page 32, section: "Class Names in Source Code".

参考:Objective-C编程语言第32页,部分:“源代码中的类名”。

#3


2  

@John and @ryanprayogo -- you are both fundamentally wrong. MyClass is a Class, which is also an object, but does not inherit from NSObject. Objective-C is kind of weird this way, but its actually brilliant when fully explained (See here). The answer here, though, is as @yehnan said, that a class name can be either a type name for declarators and casts, or as a receiver for messages. The implementation of [MyClass class] returns self (which is, within the method, MyClass). Also as @yehnan said, the language could support passing it as an argument, although it simply doesn't.

@John和@ryanprayogo——你们俩从根本上都是错误的。MyClass是一个类,也是一个对象,但不从NSObject继承。Objective-C有点奇怪,但是当完全解释的时候它确实很精彩(见这里)。不过,这里的答案正如@yehnan所说,类名可以是声明者和类型转换的类型名,也可以是消息的接收者。[MyClass]的实现返回self(在方法中是MyClass)。同样,正如@yehnan所说,语言可以支持将它作为一个参数传递,尽管它只是不支持。

#4


1  

My first glance answer is because [MyClass class] return a object of type Class, and MyClass doesn't inherit from Class...

我的第一个答案是,因为[MyClass类]返回一个类类型的对象,而MyClass不从类继承……

#5


1  

@yehnan captures it well, but I'll expand on this a little. Yes, the compiler could be modified to automatically convert a class identifier into its applicable Class in places where it is an argument rather than only when it is the target of a message. But there's not a lot of call for that kind of added complexity in the compiler (translated: slower, harder to detect coding errors). You shouldn't be calling things that return Class very often. If you are, then your object model is broken. Class-checking should be the last, desperate approach after everything else has failed (most notably correct typing and then respondsToSelector:). So for this kind of rare event, it doesn't make a lot of sense to complicate the compiler this way.

@yehnan很好地抓住了这一点,但我还是要稍微扩展一下。是的,可以对编译器进行修改,以便在作为参数的地方自动将类标识符转换为其适用的类,而不是仅当它是消息的目标时。但是在编译器中并没有太多的要求增加这种复杂性(换句话说:更慢,更难检测编码错误)。你不应该经常调用返回类的东西。如果是,那么对象模型就被破坏了。类检查应该是所有其他方法失败后的最后一种绝望的方法(最值得注意的是,正确输入然后respondsToSelector:)。所以对于这种罕见的事件,用这种方式使编译器复杂化并没有多大意义。

#6


-1  

Because what the isKindOfClass expects is a "class" and that's what get returned from invoking: [MyClass class]

因为isKindOfClass期望的是一个“类”,这就是从调用返回的结果:[MyClass类]

#7


-1  

I'm thinking that MyClass is actually a meta-class. You send it the class message to get the actual class (of type Class).

我认为MyClass实际上是一个元类。您将类消息发送给它以获取实际的类(类型类)。

#8


-2  

MyClass is not of type Class.

MyClass不是类型类。

[MyClass class] is of type Class.

[MyClass类]是类型类。

If you are familiar with Java, the concept is the same.

如果您熟悉Java,概念是一样的。

java.lang.String is not of type java.lang.Class

. lang。String不是java.lang.Class类型

java.lang.String.getClass() is of type java.lang.Class

getclass()类型为java.lang.Class