Разрешено ли инициализаторам Objective C иметь одно и то же имя? - PullRequest
5 голосов
/ 27 апреля 2010

Я сталкиваюсь со странной проблемой в Objective-C, когда у меня есть два класса, использующие инициализаторы с одинаковыми именами, но с разными типами аргументов. Например, допустим, я создаю классы A и B:

хиджра:

#import <Cocoa/Cocoa.h>

@interface A : NSObject {
}

- (id)initWithNum:(float)theNum;

@end

a.m:

#import "A.h"

@implementation A

- (id)initWithNum:(float)theNum
{
    self = [super init];
    if (self != nil) {
        NSLog(@"A: %f", theNum);
    }
    return self;
}

@end

B.h:

#import <Cocoa/Cocoa.h>

@interface B : NSObject { 
}

- (id)initWithNum:(int)theNum;

@end

B.m:

#import "B.h"

@implementation B

- (id)initWithNum:(int)theNum
{
    self = [super init];
    if (self != nil) {
        NSLog(@"B: %d", theNum);
    }
    return self;
}

@end

main.m:

#import <Foundation/Foundation.h>

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

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    A *a = [[A alloc] initWithNum:20.0f];   
    B *b = [[B alloc] initWithNum:10];

    [a release];
    [b release];

    [pool drain];
    return 0;
}

Когда я запускаю это, я получаю следующий вывод:

2010-04-26 20:44:06.820 FnTest[14617:a0f] A: 20.000000
2010-04-26 20:44:06.823 FnTest[14617:a0f] B: 1

Если я переверну порядок импорта, чтобы он сначала импортировал B.h, я получу:

2010-04-26 20:45:03.034 FnTest[14635:a0f] A: 0.000000
2010-04-26 20:45:03.038 FnTest[14635:a0f] B: 10

По какой-то причине кажется, что он использует тип данных, определенный в зависимости от того, какой @interface будет включен первым для обоих классов. Я сделал несколько шагов по отладчику и обнаружил, что указатель isa для объектов a и b заканчивается одинаково. Я также обнаружил, что если я больше не делаю встроенные вызовы alloc и init, кажется, что обе инициализации работают должным образом, например ::1010*

A *a = [A alloc];
[a initWithNum:20.0f];

Если я использую это соглашение, когда создаю a и b, я получаю правильный вывод, и указатели isa кажутся разными для каждого объекта.

Я что-то не так делаю? Я бы подумал, что несколько классов могут иметь одинаковые имена инициализаторов, но, возможно, это не так.

1 Ответ

5 голосов
/ 27 апреля 2010

Проблема в том, что метод +alloc возвращает объект типа id, поэтому компилятор не может решить, какую сигнатуру метода использовать. Вы можете заставить свое приложение выбрать правильный селектор несколькими способами. Можно было бы разыграть возврат из alloc, поэтому:

A* a = [(A*)[A alloc] initWithNum:20.f];
B* b = [(B*)[B alloc] initWithNum:10];

Или вы можете переопределить alloc в вашем классе и вернуть что-то более конкретное, хотя я бы сам этого не сделал. Итак:

+ (A*)alloc { return [super alloc]; }

Наконец, и то, что я бы выбрал лично, сделает селекторы более наглядными:

// A.h
- (id)initWithFloat:(float)theNum;

// B.h
- (id)initWithInteger:(int)theNum;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...