Objective-C是否支持特征/混合蛋白? [英] Does Objective-C support traits/mixins?

查看:110
本文介绍了Objective-C是否支持特征/混合蛋白?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Objective-C中是否有任何模拟特质或混合蛋白的技术?

Are there any techniques for emulating traits or mixins in Objective-C?

例如,在Scala中,我可以执行以下操作:

In Scala, for example, I can do something like this:

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,我所有的控制器子类都来自该UIViewController,但是如果我可以将其分解并让特定的控制器继承特定的行为,那将变得更加整洁.

It's basically a way to combine (or mix in) multiple pieces of functionality into a single class. So right now I have kind of an all-purpose UIViewController that all of my controllers subclass from, but it would be neater if I could break that down and have specific controllers inherit specific behavior.

推荐答案

没有直接语言支持,但是您可以在消息转发中完成类似的操作.假设您有特征类"Foo"和"Bar",它们分别定义方法"-doFoo"和"-doBar".您可以将班级定义为具有特征,例如:

There's no direct language support, but you could accomplish something similar with message forwarding. Let's say you have trait classes "Foo" and "Bar", which define methods "-doFoo" and "-doBar", respectively. You could define your class to have traits, like this:

@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的实例,并添加所需的任何特征"对象:

Now, you can create instances of MyClassWithTraits, and add whatever "trait" objects you'd like:

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

如果希望该类的每个实例具有相同的特征,则可以在MyClassWithTraits的-init方法中对-addTrait:进行这些调用.或者,您可以像我在这里所做的那样进行操作,它允许您为每个实例分配不同的特征集.

You could make these calls to -addTrait: in MyClassWithTraits' -init method, if you want every instance of that class to have the same kind of traits. Or, you could do it like I've done here, which allows you to assign a different set of traits to each instance.

然后您可以调用-doFoo-doBar,就好像它们是由小部件实现的一样,即使消息已转发到其特征对象之一:

And then you can call -doFoo and -doBar as if they were implemented by widget, even though the messages are being forwarded to one of its trait objects:

[widget doFoo];
[widget doBar];

(编辑:添加了错误处理.)

(Edit: Added error handling.)

这篇关于Objective-C是否支持特征/混合蛋白?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆