2013-02-28 6 views
3

Я понимаю, что переопределение метода с помощью категории - это обескураженная практика. Тем не менее, мне приходится иметь дело с некоторым кодом, который делает это. Когда я запускал следующий код, я был сначала удивлен тем, что мой метод категории был вызван в обоих случаях, хотя думать о том, как линкер должен был принять решение во время ссылки для любого данного символа, заставило меня чувствовать себя лучше.Будет ли метод, переопределяемый в категории, всегда иметь приоритет над исходной реализацией?

Мой вопрос: Предполагая, что в других играх нет других категорий, кроме тех, которые я создаю, я уверен, что реализация в моей категории всегда будет логикой, которая называется до тех пор, пока заголовок для нее импортируется откуда-то?

someObject.h

#import <Foundation/Foundation.h> 

@interface SomeObject : NSObject 

- (void)doSomething; 

@end 

someObject.m

#import "SomeObject.h" 

@implementation SomeObject 

- (void)doSomething 
{ 
    NSLog(@"Original"); 
} 

@end 

SomeObject + Cat.h

#import <Foundation/Foundation.h> 

#import "SomeObject.h" 

@interface SomeObject (SomeObject) 

- (void)doSomething; 

@end 

SomeObject + Cat.m

#import "SomeObject+Cat.h" 

@implementation SomeObject (SomeObject) 

- (void)doSomething 
{ 
    NSLog(@"New!"); 
} 

@end 

someObjectUser.h

#import <Foundation/Foundation.h> 

@interface SomeObjectUser : NSObject 

- (void)useSomeObject; 

@end 

someObjectUser.m

#import "SomeObjectUser.h" 

#import "SomeObject.h" 

@implementation SomeObjectUser 

- (void)useSomeObject 
{ 
    [[SomeObject new] doSomething]; 
} 

@end 

Test.m

- (void)testExample 
{ 
    [[SomeObject new] doSomething]; 
    [[SomeObjectUser new] useSomeObject]; 
} 

Результат

2013-02-28 11:32:37.417 CategoryExample[933:907] New! 
2013-02-28 11:32:37.419 CategoryExample[933:907] New! 
+0

@NikolaiRuhe Я не согласен, вопросы принципиально разные. –

+0

@MikeD Вопрос немного другой, но ответ верен для обоих вопросов. – Sulthan

+0

Сначала я прочитал этот вопрос и теперь вижу, как там есть ответ, однако тот факт, что руководство говорит, что неопределенное поведение «менее вероятно, проблема» заставило меня задуматься о том, есть ли дополнительные сведения, которые будут здесь. –

ответ

5

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

Я сомневаюсь, что это вообще важно, импортируете ли вы заголовок категории или нет. Заголовки - это информация для компилятора; категории добавляются к классам во время выполнения, и выбор какой реализации используется для данного метода происходит во время выполнения. Что еще более важно ...

От Objective-C Programming Guide:

Если имя метода, объявленного в категории такой же, как метод в исходном классе, или метода в другой категории на одной и той же класс (или даже суперкласс), поведение не определено, к которому применяется реализация метода во время выполнения. Это менее вероятно, будет проблемой , если вы используете категории со своими собственными классами, но может вызвать проблемы с при использовании категорий для добавления методов к стандартному какао или Классы Cocoa Touch.

(выделено мной.)

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

+0

Странно! Если я не схожу с ума, это отвратительное изменение от старого поведения, которое заключалось в том, что категории всегда переопределяли методы, не относящиеся к категории, но не было никакого способа сделать приоритет одной категории над другой. Хороший улов. – Chuck

+0

Эй, @ Чак. Я не думаю, что что-то действительно изменилось - поскольку методы категории обязательно добавляются в класс после создания класса, я бы полностью ожидал, что реализация категории всегда будет использоваться. Но OP запросил * гарантию *, очевидно, сильный термин, и документы говорят * undefined *, поэтому ... – Caleb

+0

Также из документации: «Определенный каркасом метод, который вы пытаетесь переопределить, сам может быть реализован в категории, и поэтому реализация с приоритетом не определена ». Если бы в каждом случае это не было определено, почему бы им не сказать это? Я сомневаюсь в документации по этому вопросу ... –

0

UPDATE:

В SO ответить связаны ниже, ссылка, указывающая на Objective-C Категория Docs мертв. Here is more up to date version. Существует раздел об избежании столкновений имен.


Да, по этой SO answer, (я отправлю официальную ссылку Apple, когда я его найти).

Некоторые предупреждения, оригинальный метод будет недоступен, но вы всегда можете до super, нет гарантии, что метод, объявленный в другой категории (в том же классе), будет переопределен.