Поддерживает ли Objective-C черты / миксины? - PullRequest
12 голосов
/ 09 апреля 2011

Существуют ли какие-либо методы для эмуляции черт или миксинов в Objective-C?

В Scala, например, я могу сделать что-то вроде этого:

trait ControllerWithData {
  def loadData = ...
  def reloadData = ...
  def elementAtIndex = ...
}

trait ControllerWithStandardToolbar {
  def buildToolbar = ...
  def showToolbar = ...
  def hideToolbar = ...
}

class MyTableController extends ControllerWithData 
                        with ControllerWithStandardToolbar {
  def loadView = {
     super.loadView

     loadData
     buildBar
  }
}

По сути, это способ объединить (или смешать) несколько частей функциональности в один класс. Так что сейчас у меня есть универсальный UIViewController, из которого все мои контроллеры подклассы, но было бы лучше, если бы я мог разбить его и иметь конкретные контроллеры, наследующие определенное поведение.

Ответы [ 3 ]

18 голосов
/ 09 апреля 2011

Прямой языковой поддержки нет, но вы можете добиться чего-то похожего с пересылкой сообщений.Допустим, у вас есть классы признаков "Foo" и "Bar", которые определяют методы "-doFoo" и "-doBar" соответственно.Вы можете определить свой класс, чтобы иметь черты, например:

@interface MyClassWithTraits : NSObject {
    NSMutableArray *traits;
}
@property (retain) NSMutableArray* traits;

-(void) addTrait:(NSObject*)traitObject;
@end

@implementation MyClassWithTraits
@synthesize traits;

-(id)init {
    if (self = [super init]) {
        self.traits = [NSMutableArray array];
    }
    return self;
}

-(void) addTrait:(NSObject*)traitObject {
    [self.traits addObject:traitObject];
}

/*  Here's the meat - we can use message forwarding to re-send any messages
    that are unknown to MyClassWithTraits, if one of its trait objects does
    respond to it.
*/
-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector {
    // If this is a selector we handle ourself, let super handle this
    if ([self respondsToSelector:aSelector])
        return [super methodSignatureForSelector:aSelector];

    // Look for a trait that handles it
    else
        for (NSObject *trait in self.traits)
            if ([trait respondsToSelector:aSelector])
                return [trait methodSignatureForSelector:aSelector];

    // Nothing was found
    return nil;
}

-(void) forwardInvocation:(NSInvocation*)anInvocation {
    for (NSObject *trait in self.traits) {
        if ([trait respondsToSelector:[anInvocation selector]]) {
            [anInvocation invokeWithTarget:trait];
            return;
        }
    }

    // Nothing was found, so throw an exception
    [self doesNotRecognizeSelector:[anInvocation selector]];
}
@end

Теперь вы можете создавать экземпляры MyClassWithTraits и добавлять любые объекты «черты», которые вам нравятся:

MyClassWithTraits *widget = [[MyClassWithTraits alloc] init];
[widget addTrait:[[[Foo alloc] init] autorelease]];
[widget addTrait:[[[Bar alloc] init] autorelease]];

Вы можете сделать эти вызовы для -addTrait: в методе -init MyClassWithTraits, если вы хотите, чтобы у каждого экземпляра этого класса были одинаковые черты.Или вы можете сделать это так, как я это сделал здесь, что позволяет назначать разные наборы характеристик для каждого экземпляра.

И затем вы можете вызывать -doFoo и -doBar, как если бы они были реализованыс помощью виджета, даже если сообщения пересылаются одному из его объектов признаков:

[widget doFoo];
[widget doBar];

( Редактировать : добавлена ​​обработка ошибок.)

0 голосов
/ 30 января 2017

Черты или миксины не поддерживаются Objective-C, у вас есть только встроенная опция категорий. Но, к счастью, в Objective-C Runtime есть почти все инструменты для реализации собственной идеи смешивания или черт с добавлением методов и свойств в ваш класс во время выполнения. Вы можете узнать больше о возможностях, которые Objective-C Runtime предоставляет для вас, на веб-сайте документации Apple Objective-C Runtime Docs

Идея:

1) Вы можете создать протокол Objective-C (Mixin), в котором вы будете объявлять свойства и методы.

2) Затем вы создаете класс (реализация Mixin), который будет реализовывать методы из этого протокола.

3) Вы делаете свой некоторый класс, в котором вы хотите предоставить возможность композиции с миксинами, чтобы соответствовать этому протоколу (Mixin).

4) Когда ваше приложение запускается, вы добавляете во время выполнения Objective C все реализации из класса (реализация Mixin) и свойства, объявленные в (Mixin), в ваш класс.

5) вуаля:)

Или вы можете использовать несколько готовых проектов с открытым исходным кодом, таких как " Alchemiq "

0 голосов
/ 09 апреля 2011

Вы, вероятно, ищете категории. Смотри http://macdevelopertips.com/objective-c/objective-c-categories.html.

...