Подтвердить что ты не робот

Добавление одной и той же категории в несколько классов

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

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

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

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

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

Спасибо.

4b9b3361

Ответ 1

Я до сих пор не знаю, как это сделать в 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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

Отметьте этот вопрос, он может дать дополнительную информацию.

Ответ 6

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

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