Интересное поведение Objective-c методом - PullRequest
1 голос
/ 06 января 2012

Почему вызов _something из foo вызывает реализацию B _something?

@interface A
@end

@implementation A
- (void) _something {
    NSLog(@"A");
}
- (void) foo {
    [self _something];
}
@end

@interface B : A
@end

@implementation B
- (void) _something {
        NSLog(@"B");
}
@end

Ответы [ 4 ]

2 голосов
/ 06 января 2012

Это будет сделано, если вы вызовете -foo для экземпляра B, потому что B переопределяет метод -_something.

Метод отправки реализован в Objective-C путем отправки сообщения, поэтому метод foo отправляет сообщение получателю, сообщая ему сделать _something.Получатель (или среда выполнения от имени получателя) ищет то, что он должен делать в ответ на любое сообщение;в сообщении указывается метод селектор , и объект выполняет соответствующую реализацию .Существует другая реализация _something для классов A и B.

2 голосов
/ 06 января 2012

Вызывает реализацию B, только если она вызывается для объекта класса B.Это связано с тем, что в target-C все методы являются «виртуальными» (хотя это значительное упрощение), в основном из-за его динамической отправки .

Чтобы быть более точным, Objective-Cне имеет методов.Вместо этого вы отправляете «сообщения» объектам.Он обрабатывается во время выполнения, и сам объект решает, как «ответить» на это сообщение.По умолчанию он ищет селектор в своем классе и вызывает соответствующий «метод» (который в случае _something различен для A и B).

1 голос
/ 06 января 2012

Если вы вызвали _something для объекта класса B, то вы по существу переопределили его:

B *myClass = [B alloc] init];
[myClass _something];

Выход:

B

Если бы вы сделали следующий пример, у вас не будет переопределения _something, и вы получите вывод класса A:

A *myClass = [A alloc] init];
[myClass _something];

Выход:

A

Это действительно зависит от класса, из которого вы создали экземпляр вашего объекта из-за динамической природы сообщений:

A *myClass = [B alloc] init];
[myClass _something];

Вывод:

B
1 голос
/ 06 января 2012

Если объект является B, вы назвали _something, поэтому вы получите код для B '_something. Если вы ожидали реализации A, вы неправильно понимаете передачу сообщения target-C. Код для метода определяется во время выполнения. Если вы пришли из C ++, представьте, что все методы являются виртуальными.

...