Когда я использую точечную нотацию Objective C для установки члена подкласса, я получаю ошибку компилятора - PullRequest
1 голос
/ 18 февраля 2012

Enrivonment: Mac OS X 10.6.8 Xcode 3.2.3

@interface A : NSObject
@end

@implementation: A
@end

@interface B : A
{
    int b;
}
@property int b;
@end

@implementation B
@synthesize b;
@end

#import "A.h"
#import "B.h"

int main()
{
    A *pa;
    pa = [[B alloc] init];
    pa.b = 3; /*here I get a error: request for member 'b' in something 
                not a structure or union. */

    [pa setB: 3]; // this works.
    return 0;
}

Так почему же это ошибка?Как я знаю, точечные обозначения и скобочные обозначения делают одно и то же.

Ответы [ 4 ]

3 голосов
/ 18 февраля 2012

pa - указатель на экземпляр класса A, который не имеет свойства b. Вам нужно привести его к указателю на B:

((B*)pa).b = 3;

В этой строке нет ошибки компилятора, но есть предупреждение о неизвестном селекторе (потому что pa является указателем на A):

[pa setB: 3];

Но в случае свойства компилятору необходимо знать, какое это свойство, чтобы иметь возможность генерировать соответствующее сообщение.

0 голосов
/ 18 февраля 2012

вы определяете объект класса и распределяете объект класса b таким образом, когда вы тоже хотите использовать его после приведения типа этого указателя.

((B *) pa) .b = 3;тогда его не выдают никакой ошибки.

0 голосов
/ 18 февраля 2012

Во время выполнения они делают то же самое, да, но вы все еще во время компиляции.

Во время компиляции, если вы используете точечную нотацию, компилятор не даст вам уйти с чем-то, что, по его мнению, может не работать. Поскольку вы обращаетесь к объекту через тип базового класса A, а свойство относится к типу B, компилятор выдает ошибку.

Если, с другой стороны, вы используете скобочные обозначения, компилятор менее категоричен и выдает только предупреждение. Он допускает, что вы могли бы знать, что делаете :-), но он дает вам знать, что он не видел метода с именем setB: в интерфейсе класса A.

Чтобы избавиться от предупреждения, объявите переменную lke вот так:

id pa;

Использование типа id (что переводится как «указатель на объект») позволяет отправлять любое сообщение на объект без предупреждения, поскольку теперь компилятор не делает никаких предположений относительно типа объекта , Вы попали в удивительный мир полностью динамического языка Objective-C: -)

0 голосов
/ 18 февраля 2012

Вы объявили PA как тип A *

Затем вы выделяете B и присваиваете pa. Поскольку B является подклассом A, он работает.

Тогда вы ссылаетесь на п.б. A * (который является типом переменной) не имеет члена b. Это должно работать, если вы разыгрываете его:

((*B)pa).b = 3;

setB работает, поскольку компилятор попытается отправить селектор setB:, на который объект может или не может ответить.

Возможно, вы получите предупреждение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...