Соответствие метода наследования Objective C - PullRequest
1 голос
/ 16 декабря 2009

Я столкнулся со странным сценарием, связанным с наследованием классов в Objective-C.

Допустим, у меня есть три класса A, B и C, которые наследуются от базового класса X. Классы A, B и X имеют конструктор:

- (id)InitWithString:(NSString*)someString andDelegate:(id<SomeProtocol>)aDelegate

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

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

Я пытался заставить конструкторы возвращать A *, B * или C * вместо анонимного идентификатора, хотя это по-прежнему не решает проблему.

Единственное, что работает, это приведение к нужному классу, например так:

instanceOfA = [(A*)[A alloc] InitWithString:@"" andDelegate:aDelegate];

Это кажется излишним и ненужным. Я, наверное, здесь упускаю что-то очевидное.

Ответы [ 2 ]

1 голос
/ 16 декабря 2009

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

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

Чтобы обойти это, нужно инициализировать класс в два этапа:

ClassA *test = [ClassA alloc];
test = [test initWithString:@"" andDelegate:delegate];

В этом случае анализатор знает, что тест относится к типу ClassA, и выбирает правильный селектор. Кажется, что это не так умно, чтобы сказать, какие типы промежуточных объектов не назначены переменной, а затем просто всегда предполагает, что они равны id.

1 голос
/ 16 декабря 2009

Проблема заключается в объявлении метода, который определяет параметр указанного типа.

Вы должны сделать объявление как можно более универсальным, чтобы оно действовало для всех классов объекта, переданного в качестве последних параметров. если все протоколы наследуются от родительского протокола, вы можете объявить метод как - (id)initWithString:(NSString*)someString andDelegate:(id<ParentProtocol>)aDelegate; иначе вы можете использовать более общее определение - (id)initWithString:(NSString*)someString andDelegate:(id)aDelegate

...