Инициализаторам Objective C позволяют совместно использовать то же имя?

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

A.h:

#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 заканчивается то же. Я также узнал, что, если я больше не делаю выделение и вызовы init встроенными, обе инициализации, кажется, работают правильно, например:

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

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

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

5
задан NattKatt 27 April 2010 в 01:56
поделиться

1 ответ

Проблема в том, что метод +alloc возвращает объект типа id, поэтому компилятор не может решить, какую сигнатуру метода использовать. Вы можете заставить ваше приложение выбрать правильный селектор несколькими способами. Одним из них может быть приведение return из 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;
5
ответ дан 14 December 2019 в 19:06
поделиться
Другие вопросы по тегам:

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