Почему мы должны сделать [класс MyClass] в Objective C?

В Objective C можно вызвать методы класса с:

[MyClass aClassMethod];

И можно запросить вид экземпляра с:

[someInstance isKindOfClass:[MyClass class]];

Но, почему мы должны сделать [MyClass class], и не просто обеспечивают MyClass как это:

[someInstance isKindOfClass:MyClass];

Есть ли причина, что компилятор соглашается с обнаружением MyClass как получатель (тип указателя), но не как аргумент? Действительно ли это - ограничение парсинга языка? Или возможно ограничение компилятора?

44
задан dreamlax 24 June 2010 в 04:19
поделиться

8 ответов

Оооо... забавный вопрос. Ответ - с-изм.

Рассмотрим:

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

Теперь, допустим, у вас есть:

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

В этом контексте компилятор видит MyClass как определение типа. В * говорится, что переменная m является указателем на кусок памяти, который содержит один (или много - не забудьте свое указательное фу в Си) экземпляров MyClass.

Другими словами, MyClass - это тип.

Но в контексте чего-то вроде:

[someInstance isKindOfClass: x ];

x должно быть rvalue или, говоря человеческим языком, значение выражения. Тип, однако, не может быть использован в качестве r-значения.

То, что [класс MyClass] работает, на самом деле является небольшим хаком, как в языке, так и в компиляторе, поскольку грамматика специально позволяет имени типа быть получателем сообщения (быть целью вызова метода).

И, собственно говоря, вы можете сделать:

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

Все будет работать. Однако вы не можете сделать следующее но сообщение об ошибке просвечивает:

[NSUInteger class];

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


Итак, почему бы не сделать специальный регистр везде как голое имя?

Это приводит к слиянию имен типов и rvalues, и вы быстро оказываетесь вынуждены проглотить что-то вроде [foo isKindOfClass: (MyClass)];, при этом блевая на [foo isKindOfClass: (MyClass *)];, который затем вторгается на территорию типизации довольно неудобным образом.

41
ответ дан 26 November 2019 в 22:19
поделиться

Мой ответ на первый взгляд - потому что [MyClass class] возвращает объект типа Class, а MyClass не наследуется от Class...

1
ответ дан 26 November 2019 в 22:19
поделиться

@yehnan хорошо это передает, но я немного расскажу об этом. Да, компилятор может быть модифицирован для автоматического преобразования идентификатора класса в его применимый Class в тех местах, где он является аргументом, а не только тогда, когда он является целью сообщения. Но в компиляторе нет особых требований к такой дополнительной сложности (в переводе: медленнее, труднее обнаруживать ошибки кодирования). Не следует слишком часто называть вещи, которые возвращают Class . Если да, то ваша объектная модель сломана. Проверка классов должна быть последним, отчаянным подходом после того, как все остальное потерпело неудачу (в первую очередь правильная типизация, а затем responseToSelector: ). Так что для такого редкого случая нет смысла усложнять компилятор таким образом.

1
ответ дан 26 November 2019 в 22:19
поделиться

@John и @ryanprayogo - вы оба в корне неправы. MyClass - это Class, который также является объектом, но не наследуется от NSObject. Objective-C немного странен в этом смысле, но на самом деле он великолепен, когда полностью объяснен (См. здесь). Ответ здесь, однако, как сказал @yehnan, заключается в том, что имя класса может быть либо именем типа для деклараторов и кастов, либо приемником для сообщений. Реализация [MyClass class] возвращает self (который внутри метода является MyClass). Также, как сказал @yehnan, язык мог бы поддерживать передачу self в качестве аргумента, но просто не поддерживает.

2
ответ дан 26 November 2019 в 22:19
поделиться

MyClass не относится к типу Class .

[MyClass class] имеет тип Class .

Если вы знакомы с Java, концепция та же.

java.lang.String не относится к типу java.lang.Class

java.lang.String.getClass () имеет тип java.lang.Class

-2
ответ дан 26 November 2019 в 22:19
поделиться

Я думаю, что MyClass на самом деле является метаклассом. Вы посылаете ему сообщение class, чтобы получить реальный класс (типа Class).

-1
ответ дан 26 November 2019 в 22:19
поделиться

Потому что то, что isKindOfClass ожидает, это "класс", и это то, что возвращается при вызове: [MyClass class]

-1
ответ дан 26 November 2019 в 22:19
поделиться

Интересно.

В Objective-C имя класса имеет две роли: как тип данных и как объект класса. В качестве имени типа данных вы можете делать такие вещи, как:

MyClass *anObject;

В качестве объекта класса имя класса может обозначать объект класса только как получатель сообщения. Вот почему вы должны использовать

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

Однако я не думаю, что это тот ответ, который может удовлетворить ваши потребности. Для меня ответ - «да, то, что вы хотите, вполне правдоподобно. Но в спецификации сказано иное».

Ссылка: Язык программирования Objective-C Стр. 32, раздел: «Имена классов в исходном коде» .

7
ответ дан 26 November 2019 в 22:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: