Добавление одной категории в несколько классов - PullRequest
20 голосов
/ 26 февраля 2012

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

У меня есть существующие категории на NSManagedObject подклассах (Book, Chapter, Page), и я хотел бы добавить общие функциональные возможности для этих подклассов простым и понятным способом.

Один из способов - добавить категорию к их общему суперклассу (NSManagedObject), но это приведет к добавлению методов категории ко всем подклассам NSManagedObject, когда я хочу добавить методы к трем подклассам NSManagedObject (Book, Chapter, Page).

Другим решением было бы создать подкласс NSManagedObject, а затем Book, Chapter и Page наследовать от этого NSManagedObject подкласса. Это самый чистый, самый прямой подход. Большим недостатком этого подхода является то, что когда модель данных изменяется и Xcode регенерирует подклассы, он сбрасывает их обратно к наследованию от NSManagedObject вместо SubclassedManagedObject. Я хотел бы по возможности избегать использования чего-то вроде mogenerator / Xmo'd.

Можно ли добавить одну категорию в несколько классов без дублирования кода?

Спасибо.

Ответы [ 6 ]

5 голосов
/ 10 сентября 2013

может быть, уже слишком поздно .. Но, может быть, есть один способ сделать это .. Но, вы сказали ... должен быть тот же суперкласс

Category.h

@protocol MyProtocol <NSObject>
- (NSString*)foo;
@end

@interface NSArray  (category) <MyProtocol> @end
@interface NSString (category) <MyProtocol> @end

Category.m

@interface NSObject (category) <MyProtocol> @end
@implementation NSObject (category)
- (NSString*)foo
{
    return @"bar";
}
@end

Мне это тоже не нравится, но работает

2 голосов
/ 26 февраля 2012

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

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

1 голос
/ 12 августа 2015

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

protocol Numbered {
    func number() -> Int
}

extension Numbered {
    func number() -> Int {
        return Int(arc4random()) % 10
    }
}

class Book : Numbered {

}

class Chapter : Numbered {

}

class Page : Numbered {

}

let myBook = Book()
let myChapter = Chapter()
let myPage = Page()

print("myBook.number() = \(myBook.number())")
print("myChapter.number() = \(myChapter.number())")
print("myPage.number() = \(myPage.number())")

правильно реализует number() на всех трех классах (Book, Chapter, Page):

myBook.number() = 5
myChapter.number() = 2
myPage.number() = 8
0 голосов
/ 26 февраля 2012

Немного неправильно сказать, что предоставление категории в nsmanagedobject «имеет непреднамеренное последствие добавления методов категории во все подклассы NSManagedObject».Код категории просто связывается, когда вы включаете его в файл, в котором вы его используете: вы не изменяете объект nsmanagedobject.

Тем не менее, если код должен знать о своем объекте, вы можете создать протокол, которому соответствуют эти классы, а затем использовать conformsToProtocol в вашем коде для проведения тестирования.Это, вероятно, лучший общий подход, чем тестирование для определенных типов классов.

0 голосов
/ 26 февраля 2012

Звучит так, будто вы хотите что-то вроде модуля ruby. Я не знаю ни одного способа сделать такую ​​вещь в объективе-c. Вы можете создать протокол и привести каждый из ваших классов в соответствие с вашим протоколом, но это не решает проблему совместного использования реализации методов.

Проверьте этот вопрос , он может дать некоторые дополнительные идеи.

0 голосов
/ 26 февраля 2012

Что касается остальных ваших вещей, то, насколько я знаю, вам придется вернуться и создать общий подкласс для ваших трех классов, чтобы получить то, что вы хотите.Но я могу отметить, что вместо того, чтобы делать свой собственный метод isSupported, было бы лучше просто использовать метод responsedsToSelector NSObject, чтобы сказать, реализует ли ваш класс какой-либо специальный метод, который вы хотите использовать этими тремя классами, что должно быть лучшечем проверка против всех этих классов.Выдающе лучше, если вы добавите дополнительные классы, поскольку вам не нужно поддерживать или расширять этот гигантский список проверок isMemberOfClass

...