Я сталкиваюсь с нечетной проблемой в 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 указатели, кажется, отличаются для каждого объекта.
Я делаю что-то не так? Я думал бы, что несколько классов могли иметь те же имена инициализатора, но возможно дело не в этом.
Проблема в том, что метод +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;