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

Поддерживает ли Objective-C признаки/миксины?

Существуют ли какие-либо методы для эмуляции признаков или микшинов в 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, из которого все мои подклассы контроллеров, но это было бы более аккуратно, если бы я мог сломать это и у конкретных контроллеров наследовать определенное поведение.

4b9b3361

Ответ 1

Там нет прямой поддержки языка, но вы можете выполнить что-то подобное с пересылкой сообщений. Скажем, у вас есть классы признаков "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 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: в методе MyClassWithTraits '-init, если вы хотите, чтобы каждый экземпляр этого класса имел одинаковые черты. Или, вы могли бы сделать это, как я сделал здесь, что позволяет вам назначать другой набор признаков для каждого экземпляра.

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

[widget doFoo];
[widget doBar];

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

Ответ 2

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

Идея такова:

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

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

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

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

5) voilà:)

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